├── LICENSE.md ├── README.md ├── examples └── m5voom │ ├── .gitignore │ ├── configs.h │ └── m5voom.ino ├── library.properties └── src ├── DivoomClient.cpp ├── DivoomClient.h └── libraries ├── aes ├── AES.h ├── AES128.cpp ├── AESCommon.cpp ├── AESEsp32.cpp ├── BlockCipher.cpp ├── BlockCipher.h ├── CBC.cpp ├── CBC.h ├── Cipher.cpp ├── Cipher.h ├── Crypto.cpp ├── Crypto.h └── utility │ ├── EndianUtil.h │ ├── LimbUtil.h │ ├── ProgMemUtil.h │ └── RotateUtil_2.h └── minilzo ├── lzoconf.h ├── lzodefs.h ├── minilzo.c └── minilzo.h /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 redphx 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DivoomClient for ESP32 2 | Decrypt Divoom's animations so they could be displayed on LCD screen, LED matrix... 3 | 4 | Python implementation: [redphx/apixoo](https://github.com/redphx/apixoo) 5 | 6 | # Preface 7 | I'm really really new to Arduino/C++, so if you see I wrote something stupid, feel free to correct. I really appreciate it. 8 | The library is still in early phase. 9 | 10 | # Demo 11 | ![Demo](https://user-images.githubusercontent.com/96280/216748757-42c2a993-e91c-4c64-8567-b1f133772bcc.gif) 12 | [DivoomClient on M5StickC Plus (ESP32)](https://youtube.com/watch/gyZQLm-OVRY) 13 | 14 | # How does it work? 15 | 1. Download encrypted animation from Divoom server. 16 | 2. Decrypt using AES & LZO, then translate it to understandable frames data. 17 | 3. Render frames. 18 | 19 | # How to run the example 20 | This example I made for M5StickC Plus. May or may not work on another ESP32 devices. 21 | 22 | 1. Add DivoomClient library to Arduino. 23 | 2. Download Divoom app on Android/iOS and create an account. 24 | 3. Get MD5 hash of your password. You could use [JavaScript-MD5](https://blueimp.github.io/JavaScript-MD5/). 25 | 4. Update values in `configs.h`. 26 | 5. Update `renderFrames()` if you don't use LCD screen. It should be easy to modify it for LED matrix. 27 | 5. Compile. 28 | 29 | # TODO 30 | 1. Add comments. Sorry for the lack of comments in the code. I'll update soon. 31 | 2. Don't include AES & MiniLZO libs inside the library. Maybe switching to a better AES library, if possible. 32 | 3. Fix random crashing/memory problem. I'm not good at managing memory yet, so please help me on this if you can. 33 | 4. Add support for 32x32 and 64x64 animations. Actually I already had the working code for this, but I need to make sure the library work properly on 16x16 animations first. 34 | 35 | # Acknowledgements 36 | - [khoih-prog/AsyncTCP_SSL](https://github.com/khoih-prog/AsyncTCP_SSL) 37 | - [rweather/arduinolibs](https://github.com/rweather/arduinolibs) 38 | - [bblanchon/ArduinoJson](https://github.com/bblanchon/ArduinoJson) 39 | - [lovyan03/LovyanGFX](https://github.com/lovyan03/LovyanGFX) 40 | - [minilzo](http://www.oberhumer.com/opensource/lzo/) 41 | -------------------------------------------------------------------------------- /examples/m5voom/.gitignore: -------------------------------------------------------------------------------- 1 | configs.h 2 | debug.cfg 3 | debug_custom.json 4 | *.svd 5 | -------------------------------------------------------------------------------- /examples/m5voom/configs.h: -------------------------------------------------------------------------------- 1 | #define WIFI_SSID "ssid" 2 | #define WIFI_PASSWORD "password" 3 | 4 | #define DIVOOM_EMAIL "em@il.com" 5 | #define DIVOOM_MD5_PASSWORD "0123456789abcdef0123456789abcdef" // MD5 hash of your password 6 | -------------------------------------------------------------------------------- /examples/m5voom/m5voom.ino: -------------------------------------------------------------------------------- 1 | #include "configs.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | #define LGFX_AUTODETECT 15 | #define LGFX_USE_V1 16 | #include 17 | #include 18 | 19 | #define DIVOOM_PIXEL_SIZE 7 20 | #define DIVOOM_PIXEL_SPACE 0 21 | 22 | #define DIVOOM_PER_PAGE 5 23 | 24 | // Wifi Credentials 25 | WiFiClient wifi; 26 | 27 | DivoomClient divoom_client(wifi, DIVOOM_EMAIL, DIVOOM_MD5_PASSWORD); 28 | 29 | byte *tmp_frames_data; 30 | byte rendering_frames_data[DIVOOM_ALL_FRAMES_SIZE]; 31 | 32 | int32_t center_x, center_y, start_x, start_y; 33 | static LGFX lcd; 34 | 35 | bool next_gif_ready = false; 36 | bool request_next_gif = false; 37 | 38 | DivoomFileInfoLite divoom_files_list[DIVOOM_PER_PAGE]; 39 | uint8_t divoom_files_list_count = 0; 40 | uint8_t divoom_current_page = 1; 41 | uint8_t divoom_current_gif_index = -1; 42 | DivoomPixelBeanHeader divoom_pixel_bean_header; 43 | 44 | 45 | uint16_t drawRGB24toRGB565(uint8_t r, uint8_t g, uint8_t b) { 46 | return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3); 47 | } 48 | 49 | void OnParseSuccess(DivoomPixelBeanHeader header) { 50 | Serial.println("Success"); 51 | divoom_pixel_bean_header = header; 52 | next_gif_ready = true; 53 | } 54 | 55 | void OnParseError(int8_t error) { 56 | Serial.println("ERROR"); 57 | next_gif_ready = false; 58 | request_next_gif = true; 59 | } 60 | 61 | void renderFrames(void* param) { 62 | while (!next_gif_ready) { 63 | delay(1000); 64 | } 65 | 66 | uint8_t local_total_frames; 67 | int local_speed; 68 | 69 | uint8_t frame; 70 | uint32_t i; 71 | uint8_t x, y; 72 | 73 | uint8_t grid_x, grid_y; 74 | uint8_t draw_x, draw_y; 75 | 76 | uint8_t red, green, blue; 77 | double hue, saturation, lighting, value; 78 | uint16_t pixel_color; 79 | 80 | int max_times; 81 | int times; 82 | 83 | uint32_t start_pos; 84 | uint32_t real_i; 85 | 86 | while (true) { 87 | local_total_frames = divoom_pixel_bean_header.total_frames; 88 | local_speed = min(100, max(50, (int) divoom_pixel_bean_header.speed)); 89 | 90 | memcpy(rendering_frames_data, tmp_frames_data, local_total_frames * DIVOOM_FRAME_SIZE); 91 | 92 | frame = 0; 93 | i = 0; 94 | 95 | max_times = (int) (5000 / local_speed / local_total_frames); 96 | max_times = max(3, max_times); 97 | times = 1; 98 | 99 | request_next_gif = true; 100 | while (true) { 101 | ++frame; 102 | if (frame > local_total_frames) { 103 | ++times; 104 | if (times >= max_times and next_gif_ready) { 105 | break; 106 | } 107 | frame = 1; 108 | } 109 | 110 | start_pos = (frame - 1) * DIVOOM_FRAME_SIZE; 111 | 112 | i = 0; 113 | x = 0; 114 | y = 0; 115 | 116 | grid_x = 0; 117 | grid_y = 0; 118 | 119 | while (i <= DIVOOM_FRAME_SIZE - 3) { 120 | real_i = start_pos + i; 121 | red = rendering_frames_data[real_i]; 122 | green = rendering_frames_data[real_i + 1]; 123 | blue = rendering_frames_data[real_i + 2]; 124 | pixel_color = drawRGB24toRGB565(red, green, blue); 125 | 126 | draw_x = start_x + (grid_x * (DIVOOM_PIXEL_SIZE + DIVOOM_PIXEL_SPACE) * 16) + (x * (DIVOOM_PIXEL_SIZE + DIVOOM_PIXEL_SPACE)); 127 | draw_y = start_y + (grid_y * (DIVOOM_PIXEL_SIZE + DIVOOM_PIXEL_SPACE) * 16) + (y * (DIVOOM_PIXEL_SIZE + DIVOOM_PIXEL_SPACE)); 128 | 129 | lcd.fillRect(draw_x, draw_y, DIVOOM_PIXEL_SIZE, DIVOOM_PIXEL_SIZE - 1, pixel_color); 130 | 131 | ColorConverter::RgbToHsl(red, green, blue, hue, saturation, lighting); 132 | lighting -= 0.05; 133 | lighting = max(0.0, lighting); 134 | ColorConverter::HslToRgb(hue, saturation, lighting, red, green, blue); 135 | pixel_color = drawRGB24toRGB565(red, green, blue); 136 | lcd.drawLine(draw_x, draw_y + DIVOOM_PIXEL_SIZE - 1, draw_x + DIVOOM_PIXEL_SIZE - 1, draw_y + DIVOOM_PIXEL_SIZE - 1, pixel_color); 137 | lcd.drawLine(draw_x + DIVOOM_PIXEL_SIZE - 1, draw_y, draw_x + DIVOOM_PIXEL_SIZE - 1, draw_y + DIVOOM_PIXEL_SIZE - 1, pixel_color); 138 | 139 | i += 3; 140 | ++x; 141 | 142 | if ((i / 3) % 16 == 0) { 143 | x = 0; 144 | ++y; 145 | } 146 | /* 147 | if ((i / 3) % 256 == 0) { 148 | x = 0; 149 | y = 0; 150 | 151 | ++grid_x; 152 | 153 | if (grid_x == 2) { 154 | grid_x = 0; 155 | ++grid_y; 156 | } 157 | } 158 | */ 159 | } 160 | 161 | delay(local_speed); 162 | } 163 | } 164 | } 165 | 166 | void requestNextGif() { 167 | next_gif_ready = false; 168 | 169 | divoom_current_page = random(1, 20); 170 | ++divoom_current_gif_index; 171 | 172 | if (divoom_files_list_count == 0 || divoom_current_gif_index >= divoom_files_list_count) { 173 | int category_id = random(0, 19); 174 | divoom_client.GetCategoryFileList(divoom_files_list, &divoom_files_list_count, category_id, divoom_current_page, DIVOOM_PER_PAGE); 175 | divoom_current_gif_index = -1; 176 | request_next_gif = true; 177 | return; 178 | } 179 | 180 | divoom_client.ParseFile(divoom_files_list[divoom_current_gif_index].file_id, tmp_frames_data); 181 | } 182 | 183 | void setup() { 184 | M5.begin(); 185 | 186 | lcd.init(); 187 | lcd.setRotation(0); 188 | lcd.setColorDepth(16); 189 | 190 | center_x = lcd.width() / 2; 191 | center_y = lcd.height() / 2; 192 | start_x = floor(center_x - 16 * DIVOOM_PIXEL_SIZE / 2); 193 | start_y = floor(center_y - 16 * DIVOOM_PIXEL_SIZE / 2); 194 | 195 | Serial.begin(115200); 196 | 197 | // WiFi Init 198 | WiFi.begin(WIFI_SSID, WIFI_PASSWORD); 199 | Serial.print(F("[WIFI] connecting to network ")); 200 | Serial.print(WIFI_SSID); 201 | while (WiFi.status() != WL_CONNECTED) { 202 | delay(500); 203 | Serial.print(F(".")); 204 | } 205 | Serial.println(F(" [WIFI] connected")); 206 | 207 | xTaskCreate(renderFrames, "renderFrames", DIVOOM_ALL_FRAMES_SIZE + 1000, NULL, 1, NULL); 208 | 209 | randomSeed(analogRead(0)); 210 | while (!divoom_client.LogIn()) { 211 | Serial.println(F("Logging in...")); 212 | } 213 | 214 | divoom_client.OnParseSuccess(OnParseSuccess); 215 | divoom_client.OnParseError(OnParseError); 216 | 217 | tmp_frames_data = (byte*) malloc(DIVOOM_ALL_FRAMES_SIZE); 218 | 219 | request_next_gif = true; 220 | } 221 | 222 | void loop() { 223 | M5.update(); 224 | 225 | if (M5.BtnA.wasReleased()) { 226 | Serial.println(F("pressed A")); 227 | divoom_client.AbortDownload(); 228 | } 229 | 230 | if (request_next_gif) { 231 | request_next_gif = false; 232 | requestNextGif(); 233 | } 234 | } 235 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=DivoomClient 2 | version=0.1.0 3 | author=redphx 4 | maintainer=redphx 5 | sentence=. 6 | paragraph=. 7 | category=. 8 | url=https://github.com/redphx/DivoomClient 9 | architectures=* 10 | depends=AsyncTCP_SSL,ArduinoJson,ArduinoHttpClient 11 | -------------------------------------------------------------------------------- /src/DivoomClient.cpp: -------------------------------------------------------------------------------- 1 | // #include "Arduino.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "DivoomClient.h" 7 | #include "libraries/minilzo/minilzo.h" 8 | 9 | #define STEP_HEADER_EXPECT 4 10 | 11 | const char* DivoomClient::API_DOMAIN = "app.divoom-gz.com"; 12 | const char* DivoomClient::FILE_DOMAIN = "f.divoom-gz.com"; 13 | 14 | const char* DivoomClient::ENDPOINT_USER_LOGIN = "/UserLogin"; 15 | const int DivoomClient::REQ_SIZE_USER_LOGIN = 200; 16 | const int DivoomClient::RESP_SIZE_USER_LOGIN = 2000; 17 | 18 | const char* DivoomClient::ENDPOINT_CATEGORY_FILE_LIST = "/GetCategoryFileListV2"; 19 | const int DivoomClient::REQ_SIZE_CATEGORY_FILE_LIST = 500; 20 | const int DivoomClient::RESP_SIZE_CATEGORY_FILE_LIST = 6000; 21 | 22 | const char* DivoomClient::USER_AGENT = "Aurabox/3.1.10 (iPad; iOS 14.8; Scale/2.00)"; 23 | 24 | const byte DivoomClient::AES_KEY[16] = { 0x37, 0x38, 0x68, 0x72, 0x65, 0x79, 0x32, 0x33, 0x79, 0x32, 0x38, 0x6F, 0x67, 0x73, 0x38, 0x39 }; 25 | const byte DivoomClient::AES_IV[16] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36 }; 26 | 27 | 28 | int DivoomClient::_parse_current_step; 29 | ParseSuccessHandler DivoomClient::_parse_success_cb; 30 | ParseErrorHandler DivoomClient::_parse_error_cb; 31 | 32 | byte DivoomClient::_parse_current_data[DIVOOM_FRAME_SIZE]; 33 | int DivoomClient::_parse_current_data_len; 34 | byte DivoomClient::_parse_decrypted_data[DIVOOM_FRAME_SIZE]; 35 | int DivoomClient::_parse_decrypted_data_len; 36 | DivoomPixelBeanHeader DivoomClient::_parse_pixel_bean_header; 37 | uint32_t DivoomClient::_parse_last_packet_time; 38 | 39 | byte *DivoomClient::_parse_frames_data_ptr; 40 | byte DivoomClient::_parse_current_frame; 41 | 42 | CBC DivoomClient::_aes; 43 | AsyncSSLClient DivoomClient::_tcp_client = NULL; 44 | 45 | DivoomClient::DivoomClient(WiFiClient par_wifi, const char* par_email, const char* par_md5_password) { 46 | _wifi = par_wifi; 47 | 48 | _email = par_email; 49 | _md5_password = par_md5_password; 50 | } 51 | 52 | DynamicJsonDocument DivoomClient::_Send(const char* method, const char* endpoint, DynamicJsonDocument payload=DynamicJsonDocument(0)) { 53 | Serial.println(endpoint); 54 | HttpClient client = HttpClient(_wifi, API_DOMAIN, 80); 55 | 56 | client.beginRequest(); 57 | if (method == "POST") { 58 | String post_data; 59 | serializeJson(payload, post_data); 60 | 61 | client.post(endpoint); 62 | client.sendHeader("User-Agent", USER_AGENT); 63 | client.sendHeader("Content-Type", "application/json"); 64 | client.sendHeader("Content-Length", post_data.length()); 65 | client.sendHeader("Connection", "close"); 66 | client.beginBody(); 67 | client.print(post_data); 68 | } else { 69 | client.get(endpoint); 70 | client.sendHeader("User-Agent", USER_AGENT); 71 | client.sendHeader("Connection", "close"); 72 | } 73 | client.endRequest(); 74 | 75 | int doc_size = 1000; 76 | if (endpoint == ENDPOINT_USER_LOGIN) { 77 | doc_size = RESP_SIZE_USER_LOGIN; 78 | } else { 79 | payload["UserId"] = _user_id; 80 | payload["Token"] = _token; 81 | 82 | if (endpoint == ENDPOINT_CATEGORY_FILE_LIST) { 83 | doc_size = RESP_SIZE_CATEGORY_FILE_LIST; 84 | } 85 | } 86 | 87 | String response = client.responseBody(); 88 | if (response) { 89 | Serial.println(response); 90 | client.stop(); 91 | 92 | DynamicJsonDocument doc(doc_size); 93 | DeserializationError error = deserializeJson(doc, response); 94 | if (!error) { 95 | return doc; 96 | } 97 | 98 | Serial.println(error.c_str()); 99 | } 100 | 101 | return DynamicJsonDocument(0); 102 | } 103 | 104 | DynamicJsonDocument DivoomClient::SendGet(const char* endpoint) { 105 | return _Send("GET", endpoint); 106 | } 107 | 108 | DynamicJsonDocument DivoomClient::SendPost(const char* endpoint, DynamicJsonDocument payload) { 109 | return _Send("POST", endpoint, payload); 110 | } 111 | 112 | bool DivoomClient::LogIn() { 113 | DynamicJsonDocument payload(REQ_SIZE_USER_LOGIN); 114 | payload["Email"] = _email; 115 | payload["Password"] = _md5_password; 116 | 117 | DynamicJsonDocument doc = SendPost(ENDPOINT_USER_LOGIN, payload); 118 | if (doc.isNull()) { 119 | return false; 120 | } 121 | 122 | _user_id = doc["UserId"]; 123 | _token = doc["Token"]; 124 | 125 | return true; 126 | } 127 | 128 | void DivoomClient::GetCategoryFileList(DivoomFileInfoLite *files_list, uint8_t *files_count, uint8_t category_id, uint8_t page, uint8_t per_page) { 129 | uint16_t start_num = ((page - 1) * per_page) + 1; 130 | uint16_t end_num = start_num + per_page - 1; 131 | 132 | DynamicJsonDocument payload(REQ_SIZE_CATEGORY_FILE_LIST); 133 | payload["StartNum"] = start_num; 134 | payload["EndNum"] = end_num; 135 | payload["Classify"] = category_id; 136 | payload["Version"] = 12; 137 | payload["FileSize"] = 1; // Animation 16x16 138 | payload["FileType"] = 1; // Animation 16x16 139 | payload["RefreshIndex"] = 0; 140 | payload["FileSort"] = 0; 141 | 142 | DynamicJsonDocument doc = SendPost(ENDPOINT_CATEGORY_FILE_LIST, payload); 143 | JsonArray doc_file_list = doc["FileList"]; 144 | *files_count = doc_file_list.size(); 145 | 146 | uint8_t i = -1; 147 | for (JsonObject obj: doc_file_list) { 148 | ++i; 149 | long gallery_id = obj["GalleryId"]; 150 | const char* file_id = (const char*) obj["FileId"]; 151 | 152 | Serial.println(file_id); 153 | files_list[i] = {gallery_id, file_id}; 154 | } 155 | } 156 | 157 | void DivoomClient::OnParseSuccess(ParseSuccessHandler cb) { 158 | _parse_success_cb = cb; 159 | } 160 | 161 | void DivoomClient::OnParseError(ParseErrorHandler cb) { 162 | _parse_error_cb = cb; 163 | } 164 | 165 | void DivoomClient::ParseFile(const char* fileUrl, byte *frames_data_ptr) { 166 | _aes.clear(); 167 | _aes.setKey(AES_KEY, 16); 168 | _aes.setIV(AES_IV, 16); 169 | 170 | _parse_frames_data_ptr = frames_data_ptr; 171 | _parse_current_data_len = 0; 172 | _parse_decrypted_data_len = 0; 173 | _parse_current_frame = 1; 174 | 175 | _parse_current_step = DivoomParseStep::HttpHeader; 176 | 177 | _tcp_client = AsyncSSLClient(); 178 | //_tcp_client.setNoDelay(true); 179 | _tcp_client.onData(_OnParseData); 180 | _tcp_client.onError(_OnParseError); 181 | _tcp_client.onTimeout(_OnParseTimeOut); 182 | _tcp_client.onPoll(_OnParsePoll); 183 | _tcp_client.onDisconnect(_OnParseDisconnect); 184 | 185 | // Connect to host 186 | _tcp_client.connect(FILE_DOMAIN, 80); 187 | while (!_tcp_client.connected()) { 188 | delay(100); 189 | } 190 | 191 | // Generate TCP Download command 192 | String request = "GET /"; 193 | request += fileUrl; 194 | request += " HTTP/1.1\r\n"; 195 | request += "Host: "; 196 | request += FILE_DOMAIN; 197 | request += "\r\n"; 198 | request += "User-Agent: "; 199 | request += USER_AGENT; 200 | request += "\r\n"; 201 | request += "Connection: close\r\n\r\n"; 202 | 203 | // Send download command 204 | _tcp_client.add(request.c_str(), request.length() ); 205 | _tcp_client.send(); 206 | } 207 | 208 | void DivoomClient::_OnParseData(void* arg, AsyncSSLClient* client, void *data, size_t len) { 209 | _parse_last_packet_time = millis(); 210 | 211 | if (_parse_current_step >= DivoomParseStep::End) { 212 | return; 213 | } 214 | 215 | if (_parse_current_step == DivoomParseStep::HttpHeader) { 216 | _parse_current_step = DivoomParseStep::FileHeader; 217 | return; 218 | } 219 | 220 | int data_pos = 0; 221 | while (true) { 222 | // Serial.println(data_pos); 223 | if (_parse_current_step >= DivoomParseStep::End) { 224 | return; 225 | } 226 | 227 | if (data_pos >= len) { 228 | break; 229 | } 230 | 231 | if (_parse_current_data_len < sizeof(_parse_current_data)) { 232 | int read_size = sizeof(_parse_current_data) - _parse_current_data_len; 233 | read_size = min(read_size, static_cast(len - data_pos)); 234 | memcpy(_parse_current_data + _parse_current_data_len, ((byte*) data) + data_pos, read_size); 235 | _parse_current_data_len += read_size; 236 | data_pos += read_size; 237 | } 238 | if (_parse_current_data_len < DIVOOM_FRAME_SIZE) { 239 | return; 240 | } 241 | 242 | if (_parse_current_step == DivoomParseStep::FileHeader) { 243 | if (_parse_current_data_len >= STEP_HEADER_EXPECT) { 244 | memcpy(&_parse_pixel_bean_header, _parse_current_data, STEP_HEADER_EXPECT); 245 | _parse_pixel_bean_header.speed = SWAP_INT16(_parse_pixel_bean_header.speed); 246 | 247 | Serial.println(F("---")); 248 | Serial.println(_parse_pixel_bean_header.type); 249 | Serial.println(_parse_pixel_bean_header.total_frames); 250 | Serial.println(_parse_pixel_bean_header.speed); 251 | Serial.println(F("---")); 252 | 253 | if (_parse_pixel_bean_header.total_frames > DIVOOM_MAX_FRAMES) { 254 | _parse_current_step = DivoomParseStep::Skip; 255 | _tcp_client.close(); 256 | return; 257 | } 258 | 259 | _parse_current_data_len -= STEP_HEADER_EXPECT; 260 | memmove(_parse_current_data, _parse_current_data + STEP_HEADER_EXPECT, _parse_current_data_len); 261 | _parse_current_step = DivoomParseStep::FrameData; 262 | } 263 | continue; 264 | } 265 | 266 | // Decrypt block by block 267 | int block_size = 16; 268 | byte encrypted[block_size]; 269 | byte decrypted[block_size]; 270 | 271 | div_t div_blocks = div(_parse_current_data_len, block_size); 272 | int total_blocks = div_blocks.quot; 273 | for (int i = 0; i < total_blocks; i++) { 274 | memcpy(encrypted, _parse_current_data + i * block_size, block_size); 275 | _DecryptAes(decrypted, encrypted, block_size); 276 | memcpy(_parse_decrypted_data + _parse_decrypted_data_len, decrypted, block_size); 277 | _parse_decrypted_data_len += block_size; 278 | } 279 | 280 | memmove(_parse_current_data, _parse_current_data + total_blocks * block_size, div_blocks.rem); 281 | _parse_current_data_len = div_blocks.rem; 282 | 283 | memcpy(_parse_frames_data_ptr + (_parse_current_frame - 1) * DIVOOM_FRAME_SIZE, _parse_decrypted_data, DIVOOM_FRAME_SIZE); 284 | 285 | _parse_decrypted_data_len -= DIVOOM_FRAME_SIZE; 286 | memmove(_parse_decrypted_data, _parse_decrypted_data + DIVOOM_FRAME_SIZE, _parse_decrypted_data_len); 287 | 288 | ++_parse_current_frame; 289 | if (_parse_current_frame > _parse_pixel_bean_header.total_frames) { 290 | _parse_current_step = DivoomParseStep::End; 291 | return; 292 | } 293 | } 294 | } 295 | 296 | void DivoomClient::_OnParseError(void* arg, AsyncSSLClient* client, int8_t error) { 297 | Serial.println(F("[CALLBACK] error")); 298 | _parse_current_step = DivoomParseStep::Error; 299 | } 300 | 301 | void DivoomClient::_OnParseTimeOut(void* arg, AsyncSSLClient* client, uint32_t time) { 302 | _tcp_client.free(); 303 | Serial.println(F("[CALLBACK] ACK timeout")); 304 | _parse_current_step = DivoomParseStep::TimeOut; 305 | _parse_error_cb(-2); 306 | } 307 | 308 | void DivoomClient::_OnParsePoll(void* arg, AsyncSSLClient* client) { 309 | // Serial.println(F("Polling")); 310 | if (_parse_last_packet_time == 0) { 311 | _parse_last_packet_time = millis(); 312 | return; 313 | } 314 | 315 | if (millis() - _parse_last_packet_time > DIVOOM_TIMEOUT) { 316 | Serial.println(F("Abort")); 317 | _parse_last_packet_time = 0; 318 | _parse_current_step = DivoomParseStep::Error; 319 | client->close(); 320 | } 321 | } 322 | 323 | void DivoomClient::_OnParseDisconnect(void* arg, AsyncSSLClient* client) { 324 | _tcp_client.free(); 325 | Serial.println(F("[CALLBACK] discconnected")); 326 | if (_parse_current_step == DivoomParseStep::End) { 327 | if (_parse_success_cb) { 328 | _parse_success_cb(_parse_pixel_bean_header); 329 | } 330 | } else if (_parse_error_cb) { 331 | _parse_error_cb(-1); 332 | } 333 | } 334 | 335 | void DivoomClient::AbortDownload() { 336 | _tcp_client.close(); 337 | } 338 | 339 | void DivoomClient::_DecryptAes(byte decrypted[], byte encrypted[], int len) { 340 | _aes.decrypt(decrypted, encrypted, len); 341 | } 342 | -------------------------------------------------------------------------------- /src/DivoomClient.h: -------------------------------------------------------------------------------- 1 | #ifndef DIVOOMCLIENT_H 2 | #define DIVOOMCLIENT_H 3 | 4 | #include 5 | #include 6 | #include "libraries/aes/Crypto.h" 7 | #include "libraries/aes/AES.h" 8 | #include "libraries/aes/CBC.h" 9 | #include 10 | 11 | #ifndef DIVOOM_MAX_SIZE 12 | #define DIVOOM_MAX_SIZE 16 13 | #endif 14 | 15 | #ifndef DIVOOM_MAX_FRAMES 16 | #define DIVOOM_MAX_FRAMES 60 17 | #endif 18 | 19 | #ifndef DIVOOM_TIMEOUT 20 | #define DIVOOM_TIMEOUT 10000 21 | #endif 22 | 23 | #define DIVOOM_FRAME_SIZE DIVOOM_MAX_SIZE * DIVOOM_MAX_SIZE * 3 24 | #define DIVOOM_ALL_FRAMES_SIZE DIVOOM_FRAME_SIZE * DIVOOM_MAX_FRAMES 25 | 26 | #define SWAP_INT16(x) (x >> 8) | (x << 8); 27 | 28 | struct DivoomFileInfoLite { 29 | long gallery_id; 30 | const char* file_id; 31 | // String file_name; 32 | // String content; 33 | }; 34 | 35 | 36 | struct DivoomPixelBeanHeader { 37 | uint8_t type; 38 | uint8_t total_frames; 39 | uint16_t speed; 40 | }; 41 | 42 | 43 | struct DivoomParseStep { 44 | enum step { 45 | HttpHeader, 46 | FileHeader, 47 | FrameSize, 48 | FrameData, 49 | End, 50 | Skip, 51 | Error, 52 | TimeOut, 53 | }; 54 | }; 55 | 56 | typedef std::function ParseErrorHandler; 57 | typedef std::function ParseSuccessHandler; 58 | 59 | 60 | class DivoomClient { 61 | public: 62 | DivoomClient(WiFiClient par_wifi, const char* par_email, const char* par_md5_password); 63 | 64 | bool LogIn(); 65 | DynamicJsonDocument SendGet(const char* endpoint); 66 | DynamicJsonDocument SendPost(const char* endpoint, DynamicJsonDocument payload); 67 | void GetCategoryFileList(DivoomFileInfoLite *files_list, uint8_t *files_count, uint8_t category_id, uint8_t page, uint8_t per_page); 68 | 69 | void OnParseSuccess(ParseSuccessHandler cb); 70 | void OnParseError(ParseErrorHandler cb); 71 | void ParseFile(const char* url, byte frames_data[DIVOOM_ALL_FRAMES_SIZE]); 72 | void AbortDownload(); 73 | 74 | private: 75 | static const char* API_DOMAIN; 76 | static const char* FILE_DOMAIN; 77 | 78 | static const char* ENDPOINT_USER_LOGIN; 79 | static const int REQ_SIZE_USER_LOGIN; 80 | static const int RESP_SIZE_USER_LOGIN; 81 | 82 | static const char* ENDPOINT_CATEGORY_FILE_LIST; 83 | static const int REQ_SIZE_CATEGORY_FILE_LIST; 84 | static const int RESP_SIZE_CATEGORY_FILE_LIST; 85 | 86 | static const char* USER_AGENT; 87 | 88 | static const byte AES_KEY[16]; 89 | static const byte AES_IV[16]; 90 | 91 | static const int FRAME_SIZE; 92 | 93 | WiFiClient _wifi; 94 | 95 | const char* _email; 96 | const char* _md5_password; 97 | 98 | long _user_id; 99 | long _token; 100 | 101 | DynamicJsonDocument _Send(const char* method, const char* endpoint, DynamicJsonDocument payload); 102 | 103 | static int _parse_current_step; 104 | static ParseSuccessHandler _parse_success_cb; 105 | static ParseErrorHandler _parse_error_cb; 106 | 107 | static byte _parse_current_data[DIVOOM_FRAME_SIZE]; 108 | static int _parse_current_data_len; 109 | static byte _parse_decrypted_data[DIVOOM_FRAME_SIZE]; 110 | static int _parse_decrypted_data_len; 111 | static DivoomPixelBeanHeader _parse_pixel_bean_header; 112 | static uint32_t _parse_last_packet_time; 113 | 114 | static byte *_parse_frames_data_ptr; 115 | static byte _parse_current_frame; 116 | 117 | static AsyncSSLClient _tcp_client; 118 | 119 | static void _OnParseData(void* arg, AsyncSSLClient* client, void *data, size_t len); 120 | static void _OnParseError(void* arg, AsyncSSLClient* client, int8_t error); 121 | static void _OnParseTimeOut(void* arg, AsyncSSLClient* client, uint32_t time); 122 | static void _OnParsePoll(void* arg, AsyncSSLClient* client); 123 | static void _OnParseDisconnect(void* arg, AsyncSSLClient* client); 124 | 125 | static CBC _aes; 126 | static void _DecryptAes(byte decrypted[], byte encrypted[], int len); 127 | }; 128 | 129 | #endif // DIVOOMCLIENT_H 130 | -------------------------------------------------------------------------------- /src/libraries/aes/AES.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015,2018 Southern Storm Software, Pty Ltd. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included 12 | * in all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef CRYPTO_AES_h 24 | #define CRYPTO_AES_h 25 | 26 | #include "BlockCipher.h" 27 | 28 | // Determine which AES implementation to export to applications. 29 | #if defined(ESP32) 30 | #define CRYPTO_AES_ESP32 1 31 | #else 32 | #define CRYPTO_AES_DEFAULT 1 33 | #endif 34 | 35 | #if defined(CRYPTO_AES_DEFAULT) || defined(CRYPTO_DOC) 36 | 37 | class AESTiny128; 38 | class AESTiny256; 39 | class AESSmall128; 40 | class AESSmall256; 41 | 42 | class AESCommon : public BlockCipher 43 | { 44 | public: 45 | virtual ~AESCommon(); 46 | 47 | size_t blockSize() const; 48 | 49 | void encryptBlock(uint8_t *output, const uint8_t *input); 50 | void decryptBlock(uint8_t *output, const uint8_t *input); 51 | 52 | void clear(); 53 | 54 | protected: 55 | AESCommon(); 56 | 57 | /** @cond aes_internal */ 58 | uint8_t rounds; 59 | uint8_t *schedule; 60 | 61 | static void subBytesAndShiftRows(uint8_t *output, const uint8_t *input); 62 | static void inverseShiftRowsAndSubBytes(uint8_t *output, const uint8_t *input); 63 | static void mixColumn(uint8_t *output, uint8_t *input); 64 | static void inverseMixColumn(uint8_t *output, const uint8_t *input); 65 | static void keyScheduleCore(uint8_t *output, const uint8_t *input, uint8_t iteration); 66 | static void applySbox(uint8_t *output, const uint8_t *input); 67 | /** @endcond */ 68 | 69 | friend class AESTiny128; 70 | friend class AESTiny256; 71 | friend class AESSmall128; 72 | friend class AESSmall256; 73 | }; 74 | 75 | class AES128 : public AESCommon 76 | { 77 | public: 78 | AES128(); 79 | virtual ~AES128(); 80 | 81 | size_t keySize() const; 82 | 83 | bool setKey(const uint8_t *key, size_t len); 84 | 85 | private: 86 | uint8_t sched[176]; 87 | }; 88 | 89 | class AES192 : public AESCommon 90 | { 91 | public: 92 | AES192(); 93 | virtual ~AES192(); 94 | 95 | size_t keySize() const; 96 | 97 | bool setKey(const uint8_t *key, size_t len); 98 | 99 | private: 100 | uint8_t sched[208]; 101 | }; 102 | 103 | class AES256 : public AESCommon 104 | { 105 | public: 106 | AES256(); 107 | virtual ~AES256(); 108 | 109 | size_t keySize() const; 110 | 111 | bool setKey(const uint8_t *key, size_t len); 112 | 113 | private: 114 | uint8_t sched[240]; 115 | }; 116 | 117 | class AESTiny256 : public BlockCipher 118 | { 119 | public: 120 | AESTiny256(); 121 | virtual ~AESTiny256(); 122 | 123 | size_t blockSize() const; 124 | size_t keySize() const; 125 | 126 | bool setKey(const uint8_t *key, size_t len); 127 | 128 | void encryptBlock(uint8_t *output, const uint8_t *input); 129 | void decryptBlock(uint8_t *output, const uint8_t *input); 130 | 131 | void clear(); 132 | 133 | private: 134 | uint8_t schedule[32]; 135 | }; 136 | 137 | class AESSmall256 : public AESTiny256 138 | { 139 | public: 140 | AESSmall256(); 141 | virtual ~AESSmall256(); 142 | 143 | bool setKey(const uint8_t *key, size_t len); 144 | 145 | void decryptBlock(uint8_t *output, const uint8_t *input); 146 | 147 | void clear(); 148 | 149 | private: 150 | uint8_t reverse[32]; 151 | }; 152 | 153 | class AESTiny128 : public BlockCipher 154 | { 155 | public: 156 | AESTiny128(); 157 | virtual ~AESTiny128(); 158 | 159 | size_t blockSize() const; 160 | size_t keySize() const; 161 | 162 | bool setKey(const uint8_t *key, size_t len); 163 | 164 | void encryptBlock(uint8_t *output, const uint8_t *input); 165 | void decryptBlock(uint8_t *output, const uint8_t *input); 166 | 167 | void clear(); 168 | 169 | private: 170 | uint8_t schedule[16]; 171 | }; 172 | 173 | class AESSmall128 : public AESTiny128 174 | { 175 | public: 176 | AESSmall128(); 177 | virtual ~AESSmall128(); 178 | 179 | bool setKey(const uint8_t *key, size_t len); 180 | 181 | void decryptBlock(uint8_t *output, const uint8_t *input); 182 | 183 | void clear(); 184 | 185 | private: 186 | uint8_t reverse[16]; 187 | }; 188 | 189 | #endif // CRYPTO_AES_DEFAULT 190 | 191 | #if defined(CRYPTO_AES_ESP32) 192 | 193 | /** @cond aes_esp_rename */ 194 | 195 | // The esp32 SDK keeps moving where aes.h is located, so we have to 196 | // declare the API functions ourselves and make the context opaque. 197 | // 198 | // About the only thing the various SDK versions agree on is that the 199 | // first byte is the length of the key in bytes. 200 | // 201 | // Some versions of esp-idf have a 33 byte AES context, and others 34. 202 | // Allocate up to 40 to make space for future expansion. 203 | #define CRYPTO_ESP32_CONTEXT_SIZE 40 204 | 205 | // Some of the esp-idf system headers define enumerations for AES128, 206 | // AES192, and AES256 to identify the hardware-accelerated algorithms. 207 | // These can cause conflicts with the names we use in our library. 208 | // Define our class names to something else to work around esp-idf. 209 | #undef AES128 210 | #undef AES192 211 | #undef AES256 212 | #define AES128 AES128_ESP 213 | #define AES192 AES192_ESP 214 | #define AES256 AES256_ESP 215 | 216 | /** @endcond */ 217 | 218 | class AESCommon : public BlockCipher 219 | { 220 | public: 221 | virtual ~AESCommon(); 222 | 223 | size_t blockSize() const; 224 | size_t keySize() const; 225 | 226 | bool setKey(const uint8_t *key, size_t len); 227 | 228 | void encryptBlock(uint8_t *output, const uint8_t *input); 229 | void decryptBlock(uint8_t *output, const uint8_t *input); 230 | 231 | void clear(); 232 | 233 | protected: 234 | AESCommon(uint8_t keySize); 235 | 236 | private: 237 | uint8_t ctx[CRYPTO_ESP32_CONTEXT_SIZE]; 238 | }; 239 | 240 | class AES128 : public AESCommon 241 | { 242 | public: 243 | AES128() : AESCommon(16) {} 244 | virtual ~AES128(); 245 | }; 246 | 247 | class AES192 : public AESCommon 248 | { 249 | public: 250 | AES192() : AESCommon(24) {} 251 | virtual ~AES192(); 252 | }; 253 | 254 | class AES256 : public AESCommon 255 | { 256 | public: 257 | AES256() : AESCommon(32) {} 258 | virtual ~AES256(); 259 | }; 260 | 261 | // The ESP32 AES context is so small that it already qualifies as "tiny". 262 | typedef AES128 AESTiny128; 263 | typedef AES256 AESTiny256; 264 | typedef AES128 AESSmall128; 265 | typedef AES256 AESSmall256; 266 | 267 | #endif // CRYPTO_AES_ESP32 268 | 269 | #endif 270 | -------------------------------------------------------------------------------- /src/libraries/aes/AES128.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015,2018 Southern Storm Software, Pty Ltd. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included 12 | * in all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #include "AES.h" 24 | #include "Crypto.h" 25 | #include 26 | 27 | #if defined(CRYPTO_AES_DEFAULT) || defined(CRYPTO_DOC) 28 | 29 | /** 30 | * \class AES128 AES.h 31 | * \brief AES block cipher with 128-bit keys. 32 | * 33 | * \sa AES192, AES256, AESTiny128, AESSmall128 34 | */ 35 | 36 | /** 37 | * \brief Constructs an AES 128-bit block cipher with no initial key. 38 | * 39 | * This constructor must be followed by a call to setKey() before the 40 | * block cipher can be used for encryption or decryption. 41 | */ 42 | AES128::AES128() 43 | { 44 | rounds = 10; 45 | schedule = sched; 46 | } 47 | 48 | AES128::~AES128() 49 | { 50 | clean(sched); 51 | } 52 | 53 | /** 54 | * \brief Size of a 128-bit AES key in bytes. 55 | * \return Always returns 16. 56 | */ 57 | size_t AES128::keySize() const 58 | { 59 | return 16; 60 | } 61 | 62 | bool AES128::setKey(const uint8_t *key, size_t len) 63 | { 64 | if (len != 16) 65 | return false; 66 | 67 | // Copy the key itself into the first 16 bytes of the schedule. 68 | uint8_t *schedule = sched; 69 | memcpy(schedule, key, 16); 70 | 71 | // Expand the key schedule until we have 176 bytes of expanded key. 72 | uint8_t iteration = 1; 73 | uint8_t n = 16; 74 | uint8_t w = 4; 75 | while (n < 176) { 76 | if (w == 4) { 77 | // Every 16 bytes (4 words) we need to apply the key schedule core. 78 | keyScheduleCore(schedule + 16, schedule + 12, iteration); 79 | schedule[16] ^= schedule[0]; 80 | schedule[17] ^= schedule[1]; 81 | schedule[18] ^= schedule[2]; 82 | schedule[19] ^= schedule[3]; 83 | ++iteration; 84 | w = 0; 85 | } else { 86 | // Otherwise just XOR the word with the one 16 bytes previous. 87 | schedule[16] = schedule[12] ^ schedule[0]; 88 | schedule[17] = schedule[13] ^ schedule[1]; 89 | schedule[18] = schedule[14] ^ schedule[2]; 90 | schedule[19] = schedule[15] ^ schedule[3]; 91 | } 92 | 93 | // Advance to the next word in the schedule. 94 | schedule += 4; 95 | n += 4; 96 | ++w; 97 | } 98 | 99 | return true; 100 | } 101 | 102 | /** 103 | * \class AESTiny128 AES.h 104 | * \brief AES block cipher with 128-bit keys and tiny memory usage. 105 | * 106 | * This class differs from the AES128 class in the following ways: 107 | * 108 | * \li RAM requirements are vastly reduced. The key is stored directly 109 | * and then expanded to the full key schedule round by round. The setKey() 110 | * method is very fast because of this. 111 | * \li Performance of encryptBlock() is slower than for AES128 due to 112 | * expanding the key on the fly rather than ahead of time. 113 | * \li The decryptBlock() function is not supported, which means that CBC 114 | * mode cannot be used but the CTR, CFB, OFB, EAX, and GCM modes can be used. 115 | * 116 | * This class is useful when RAM is at a premium, CBC mode is not required, 117 | * and reduced encryption performance is not a hindrance to the application. 118 | * 119 | * The companion AESSmall128 class supports decryptBlock() at the cost of 120 | * some additional memory and slower setKey() times. 121 | * 122 | * \sa AESSmall128, AES128 123 | */ 124 | 125 | /** @cond */ 126 | 127 | // Helper macros. 128 | #define KCORE(n) \ 129 | do { \ 130 | AESCommon::keyScheduleCore(temp, schedule + 12, (n)); \ 131 | schedule[0] ^= temp[0]; \ 132 | schedule[1] ^= temp[1]; \ 133 | schedule[2] ^= temp[2]; \ 134 | schedule[3] ^= temp[3]; \ 135 | } while (0) 136 | #define KXOR(a, b) \ 137 | do { \ 138 | schedule[(a) * 4] ^= schedule[(b) * 4]; \ 139 | schedule[(a) * 4 + 1] ^= schedule[(b) * 4 + 1]; \ 140 | schedule[(a) * 4 + 2] ^= schedule[(b) * 4 + 2]; \ 141 | schedule[(a) * 4 + 3] ^= schedule[(b) * 4 + 3]; \ 142 | } while (0) 143 | 144 | /** @endcond */ 145 | 146 | /** 147 | * \brief Constructs an AES 128-bit block cipher with no initial key. 148 | * 149 | * This constructor must be followed by a call to setKey() before the 150 | * block cipher can be used for encryption or decryption. 151 | */ 152 | AESTiny128::AESTiny128() 153 | { 154 | } 155 | 156 | AESTiny128::~AESTiny128() 157 | { 158 | clean(schedule); 159 | } 160 | 161 | /** 162 | * \brief Size of an AES block in bytes. 163 | * \return Always returns 16. 164 | */ 165 | size_t AESTiny128::blockSize() const 166 | { 167 | return 16; 168 | } 169 | 170 | /** 171 | * \brief Size of a 128-bit AES key in bytes. 172 | * \return Always returns 16. 173 | */ 174 | size_t AESTiny128::keySize() const 175 | { 176 | return 16; 177 | } 178 | 179 | bool AESTiny128::setKey(const uint8_t *key, size_t len) 180 | { 181 | if (len == 16) { 182 | // Make a copy of the key - it will be expanded in encryptBlock(). 183 | memcpy(schedule, key, 16); 184 | return true; 185 | } 186 | return false; 187 | } 188 | 189 | void AESTiny128::encryptBlock(uint8_t *output, const uint8_t *input) 190 | { 191 | uint8_t schedule[16]; 192 | uint8_t posn; 193 | uint8_t round; 194 | uint8_t state1[16]; 195 | uint8_t state2[16]; 196 | uint8_t temp[4]; 197 | 198 | // Start with the key in the schedule buffer. 199 | memcpy(schedule, this->schedule, 16); 200 | 201 | // Copy the input into the state and XOR with the key schedule. 202 | for (posn = 0; posn < 16; ++posn) 203 | state1[posn] = input[posn] ^ schedule[posn]; 204 | 205 | // Perform the first 9 rounds of the cipher. 206 | for (round = 1; round <= 9; ++round) { 207 | // Expand the next 16 bytes of the key schedule. 208 | KCORE(round); 209 | KXOR(1, 0); 210 | KXOR(2, 1); 211 | KXOR(3, 2); 212 | 213 | // Encrypt using the key schedule. 214 | AESCommon::subBytesAndShiftRows(state2, state1); 215 | AESCommon::mixColumn(state1, state2); 216 | AESCommon::mixColumn(state1 + 4, state2 + 4); 217 | AESCommon::mixColumn(state1 + 8, state2 + 8); 218 | AESCommon::mixColumn(state1 + 12, state2 + 12); 219 | for (posn = 0; posn < 16; ++posn) 220 | state1[posn] ^= schedule[posn]; 221 | } 222 | 223 | // Expand the final 16 bytes of the key schedule. 224 | KCORE(10); 225 | KXOR(1, 0); 226 | KXOR(2, 1); 227 | KXOR(3, 2); 228 | 229 | // Perform the final round. 230 | AESCommon::subBytesAndShiftRows(state2, state1); 231 | for (posn = 0; posn < 16; ++posn) 232 | output[posn] = state2[posn] ^ schedule[posn]; 233 | } 234 | 235 | void AESTiny128::decryptBlock(uint8_t *output, const uint8_t *input) 236 | { 237 | // Decryption is not supported by AESTiny128. 238 | } 239 | 240 | void AESTiny128::clear() 241 | { 242 | clean(schedule); 243 | } 244 | 245 | /** 246 | * \class AESSmall128 AES.h 247 | * \brief AES block cipher with 128-bit keys and reduced memory usage. 248 | * 249 | * This class differs from the AES128 class in that the RAM requirements are 250 | * vastly reduced. The key schedule is expanded round by round instead of 251 | * being generated and stored by setKey(). The performance of encryption 252 | * and decryption is slightly less because of this. 253 | * 254 | * This class is useful when RAM is at a premium and reduced encryption 255 | * performance is not a hindrance to the application. 256 | * 257 | * The companion AESTiny128 class uses even less RAM but only supports the 258 | * encryptBlock() operation. Block cipher modes like CTR, EAX, and GCM 259 | * do not need the decryptBlock() operation, so AESTiny128 may be a better 260 | * option than AESSmall128 for many applications. 261 | * 262 | * \sa AESTiny128, AES128 263 | */ 264 | 265 | /** 266 | * \brief Constructs an AES 128-bit block cipher with no initial key. 267 | * 268 | * This constructor must be followed by a call to setKey() before the 269 | * block cipher can be used for encryption or decryption. 270 | */ 271 | AESSmall128::AESSmall128() 272 | { 273 | } 274 | 275 | AESSmall128::~AESSmall128() 276 | { 277 | clean(reverse); 278 | } 279 | 280 | bool AESSmall128::setKey(const uint8_t *key, size_t len) 281 | { 282 | uint8_t *schedule; 283 | uint8_t round; 284 | uint8_t temp[4]; 285 | 286 | // Set the encryption key first. 287 | if (!AESTiny128::setKey(key, len)) 288 | return false; 289 | 290 | // Expand the key schedule up to the last round which gives 291 | // us the round keys to use for the final two rounds. We can 292 | // then work backwards from there in decryptBlock(). 293 | schedule = reverse; 294 | memcpy(schedule, key, 16); 295 | for (round = 1; round <= 10; ++round) { 296 | KCORE(round); 297 | KXOR(1, 0); 298 | KXOR(2, 1); 299 | KXOR(3, 2); 300 | } 301 | 302 | // Key is ready to go. 303 | return true; 304 | } 305 | 306 | void AESSmall128::decryptBlock(uint8_t *output, const uint8_t *input) 307 | { 308 | uint8_t schedule[16]; 309 | uint8_t round; 310 | uint8_t posn; 311 | uint8_t state1[16]; 312 | uint8_t state2[16]; 313 | uint8_t temp[4]; 314 | 315 | // Start with the end of the decryption schedule. 316 | memcpy(schedule, reverse, 16); 317 | 318 | // Copy the input into the state and reverse the final round. 319 | for (posn = 0; posn < 16; ++posn) 320 | state1[posn] = input[posn] ^ schedule[posn]; 321 | AESCommon::inverseShiftRowsAndSubBytes(state2, state1); 322 | KXOR(3, 2); 323 | KXOR(2, 1); 324 | KXOR(1, 0); 325 | KCORE(10); 326 | 327 | // Perform the next 9 rounds of the decryption process. 328 | for (round = 9; round >= 1; --round) { 329 | // Decrypt using the key schedule. 330 | for (posn = 0; posn < 16; ++posn) 331 | state2[posn] ^= schedule[posn]; 332 | AESCommon::inverseMixColumn(state1, state2); 333 | AESCommon::inverseMixColumn(state1 + 4, state2 + 4); 334 | AESCommon::inverseMixColumn(state1 + 8, state2 + 8); 335 | AESCommon::inverseMixColumn(state1 + 12, state2 + 12); 336 | AESCommon::inverseShiftRowsAndSubBytes(state2, state1); 337 | 338 | // Expand the next 16 bytes of the key schedule in reverse. 339 | KXOR(3, 2); 340 | KXOR(2, 1); 341 | KXOR(1, 0); 342 | KCORE(round); 343 | } 344 | 345 | // Reverse the initial round and create the output words. 346 | for (posn = 0; posn < 16; ++posn) 347 | output[posn] = state2[posn] ^ schedule[posn]; 348 | } 349 | 350 | void AESSmall128::clear() 351 | { 352 | clean(reverse); 353 | AESTiny128::clear(); 354 | } 355 | 356 | #endif // CRYPTO_AES_DEFAULT 357 | -------------------------------------------------------------------------------- /src/libraries/aes/AESCommon.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Southern Storm Software, Pty Ltd. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included 12 | * in all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #include "AES.h" 24 | #include "Crypto.h" 25 | #include "utility/ProgMemUtil.h" 26 | 27 | #if defined(CRYPTO_AES_DEFAULT) || defined(CRYPTO_DOC) 28 | 29 | /** 30 | * \class AESCommon AES.h 31 | * \brief Abstract base class for AES block ciphers. 32 | * 33 | * This class is abstract. The caller should instantiate AES128, 34 | * AES192, or AES256 to create an AES block cipher with a specific 35 | * key size. 36 | * 37 | * \note This AES implementation does not have constant cache behaviour due 38 | * to the use of table lookups. It may not be safe to use this implementation 39 | * in an environment where the attacker can observe the timing of encryption 40 | * and decryption operations. Unless AES compatibility is required, 41 | * it is recommended that the ChaCha stream cipher be used instead. 42 | * 43 | * Reference: http://en.wikipedia.org/wiki/Advanced_Encryption_Standard 44 | * 45 | * \sa ChaCha, AES128, AES192, AES256 46 | */ 47 | 48 | /** @cond sbox */ 49 | 50 | // AES S-box (http://en.wikipedia.org/wiki/Rijndael_S-box) 51 | static uint8_t const sbox[256] PROGMEM = { 52 | 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, // 0x00 53 | 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 54 | 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, // 0x10 55 | 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 56 | 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, // 0x20 57 | 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 58 | 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, // 0x30 59 | 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, 60 | 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, // 0x40 61 | 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 62 | 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, // 0x50 63 | 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 64 | 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, // 0x60 65 | 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, 66 | 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, // 0x70 67 | 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 68 | 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, // 0x80 69 | 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, 70 | 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, // 0x90 71 | 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, 72 | 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, // 0xA0 73 | 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 74 | 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, // 0xB0 75 | 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 76 | 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, // 0xC0 77 | 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 78 | 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, // 0xD0 79 | 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 80 | 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, // 0xE0 81 | 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, 82 | 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, // 0xF0 83 | 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 84 | }; 85 | 86 | // AES inverse S-box (http://en.wikipedia.org/wiki/Rijndael_S-box) 87 | static uint8_t const sbox_inverse[256] PROGMEM = { 88 | 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, // 0x00 89 | 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, 90 | 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, // 0x10 91 | 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 92 | 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, // 0x20 93 | 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, 94 | 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, // 0x30 95 | 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, 96 | 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, // 0x40 97 | 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 98 | 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, // 0x50 99 | 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, 100 | 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, // 0x60 101 | 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, 102 | 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, // 0x70 103 | 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 104 | 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, // 0x80 105 | 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, 106 | 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, // 0x90 107 | 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, 108 | 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, // 0xA0 109 | 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 110 | 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, // 0xB0 111 | 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, 112 | 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, // 0xC0 113 | 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, 114 | 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, // 0xD0 115 | 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 116 | 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, // 0xE0 117 | 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, 118 | 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, // 0xF0 119 | 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D 120 | }; 121 | 122 | /** @endcond */ 123 | 124 | /** 125 | * \brief Constructs an AES block cipher object. 126 | */ 127 | AESCommon::AESCommon() 128 | : rounds(0), schedule(0) 129 | { 130 | } 131 | 132 | /** 133 | * \brief Destroys this AES block cipher object after clearing 134 | * sensitive information. 135 | */ 136 | AESCommon::~AESCommon() 137 | { 138 | } 139 | 140 | /** 141 | * \brief Size of an AES block in bytes. 142 | * \return Always returns 16. 143 | */ 144 | size_t AESCommon::blockSize() const 145 | { 146 | return 16; 147 | } 148 | 149 | // Constants to correct Galois multiplication for the high bits 150 | // that are shifted out when multiplying by powers of two. 151 | static uint8_t const K[8] = { 152 | 0x00, 153 | 0x1B, 154 | (0x1B << 1), 155 | (0x1B << 1) ^ 0x1B, 156 | (0x1B << 2), 157 | (0x1B << 2) ^ 0x1B, 158 | (0x1B << 2) ^ (0x1B << 1), 159 | (0x1B << 2) ^ (0x1B << 1) ^ 0x1B 160 | }; 161 | 162 | // Multiply x by 2 in the Galois field, to achieve the effect of the following: 163 | // 164 | // if (x & 0x80) 165 | // return (x << 1) ^ 0x1B; 166 | // else 167 | // return (x << 1); 168 | // 169 | // However, we don't want to use runtime conditionals if we can help it 170 | // to avoid leaking timing information from the implementation. 171 | // In this case, multiplication is slightly faster than table lookup on AVR. 172 | #define gmul2(x) (t = ((uint16_t)(x)) << 1, \ 173 | ((uint8_t)t) ^ (uint8_t)(0x1B * ((uint8_t)(t >> 8)))) 174 | 175 | // Multiply x by 4 in the Galois field. 176 | #define gmul4(x) (t = ((uint16_t)(x)) << 2, ((uint8_t)t) ^ K[t >> 8]) 177 | 178 | // Multiply x by 8 in the Galois field. 179 | #define gmul8(x) (t = ((uint16_t)(x)) << 3, ((uint8_t)t) ^ K[t >> 8]) 180 | 181 | #define OUT(col, row) output[(col) * 4 + (row)] 182 | #define IN(col, row) input[(col) * 4 + (row)] 183 | 184 | /** @cond aes_funcs */ 185 | 186 | void AESCommon::subBytesAndShiftRows(uint8_t *output, const uint8_t *input) 187 | { 188 | OUT(0, 0) = pgm_read_byte(sbox + IN(0, 0)); 189 | OUT(0, 1) = pgm_read_byte(sbox + IN(1, 1)); 190 | OUT(0, 2) = pgm_read_byte(sbox + IN(2, 2)); 191 | OUT(0, 3) = pgm_read_byte(sbox + IN(3, 3)); 192 | OUT(1, 0) = pgm_read_byte(sbox + IN(1, 0)); 193 | OUT(1, 1) = pgm_read_byte(sbox + IN(2, 1)); 194 | OUT(1, 2) = pgm_read_byte(sbox + IN(3, 2)); 195 | OUT(1, 3) = pgm_read_byte(sbox + IN(0, 3)); 196 | OUT(2, 0) = pgm_read_byte(sbox + IN(2, 0)); 197 | OUT(2, 1) = pgm_read_byte(sbox + IN(3, 1)); 198 | OUT(2, 2) = pgm_read_byte(sbox + IN(0, 2)); 199 | OUT(2, 3) = pgm_read_byte(sbox + IN(1, 3)); 200 | OUT(3, 0) = pgm_read_byte(sbox + IN(3, 0)); 201 | OUT(3, 1) = pgm_read_byte(sbox + IN(0, 1)); 202 | OUT(3, 2) = pgm_read_byte(sbox + IN(1, 2)); 203 | OUT(3, 3) = pgm_read_byte(sbox + IN(2, 3)); 204 | } 205 | 206 | void AESCommon::inverseShiftRowsAndSubBytes(uint8_t *output, const uint8_t *input) 207 | { 208 | OUT(0, 0) = pgm_read_byte(sbox_inverse + IN(0, 0)); 209 | OUT(0, 1) = pgm_read_byte(sbox_inverse + IN(3, 1)); 210 | OUT(0, 2) = pgm_read_byte(sbox_inverse + IN(2, 2)); 211 | OUT(0, 3) = pgm_read_byte(sbox_inverse + IN(1, 3)); 212 | OUT(1, 0) = pgm_read_byte(sbox_inverse + IN(1, 0)); 213 | OUT(1, 1) = pgm_read_byte(sbox_inverse + IN(0, 1)); 214 | OUT(1, 2) = pgm_read_byte(sbox_inverse + IN(3, 2)); 215 | OUT(1, 3) = pgm_read_byte(sbox_inverse + IN(2, 3)); 216 | OUT(2, 0) = pgm_read_byte(sbox_inverse + IN(2, 0)); 217 | OUT(2, 1) = pgm_read_byte(sbox_inverse + IN(1, 1)); 218 | OUT(2, 2) = pgm_read_byte(sbox_inverse + IN(0, 2)); 219 | OUT(2, 3) = pgm_read_byte(sbox_inverse + IN(3, 3)); 220 | OUT(3, 0) = pgm_read_byte(sbox_inverse + IN(3, 0)); 221 | OUT(3, 1) = pgm_read_byte(sbox_inverse + IN(2, 1)); 222 | OUT(3, 2) = pgm_read_byte(sbox_inverse + IN(1, 2)); 223 | OUT(3, 3) = pgm_read_byte(sbox_inverse + IN(0, 3)); 224 | } 225 | 226 | void AESCommon::mixColumn(uint8_t *output, uint8_t *input) 227 | { 228 | uint16_t t; // Needed by the gmul2 macro. 229 | uint8_t a = input[0]; 230 | uint8_t b = input[1]; 231 | uint8_t c = input[2]; 232 | uint8_t d = input[3]; 233 | uint8_t a2 = gmul2(a); 234 | uint8_t b2 = gmul2(b); 235 | uint8_t c2 = gmul2(c); 236 | uint8_t d2 = gmul2(d); 237 | output[0] = a2 ^ b2 ^ b ^ c ^ d; 238 | output[1] = a ^ b2 ^ c2 ^ c ^ d; 239 | output[2] = a ^ b ^ c2 ^ d2 ^ d; 240 | output[3] = a2 ^ a ^ b ^ c ^ d2; 241 | } 242 | 243 | void AESCommon::inverseMixColumn(uint8_t *output, const uint8_t *input) 244 | { 245 | uint16_t t; // Needed by the gmul2, gmul4, and gmul8 macros. 246 | uint8_t a = input[0]; 247 | uint8_t b = input[1]; 248 | uint8_t c = input[2]; 249 | uint8_t d = input[3]; 250 | uint8_t a2 = gmul2(a); 251 | uint8_t b2 = gmul2(b); 252 | uint8_t c2 = gmul2(c); 253 | uint8_t d2 = gmul2(d); 254 | uint8_t a4 = gmul4(a); 255 | uint8_t b4 = gmul4(b); 256 | uint8_t c4 = gmul4(c); 257 | uint8_t d4 = gmul4(d); 258 | uint8_t a8 = gmul8(a); 259 | uint8_t b8 = gmul8(b); 260 | uint8_t c8 = gmul8(c); 261 | uint8_t d8 = gmul8(d); 262 | output[0] = a8 ^ a4 ^ a2 ^ b8 ^ b2 ^ b ^ c8 ^ c4 ^ c ^ d8 ^ d; 263 | output[1] = a8 ^ a ^ b8 ^ b4 ^ b2 ^ c8 ^ c2 ^ c ^ d8 ^ d4 ^ d; 264 | output[2] = a8 ^ a4 ^ a ^ b8 ^ b ^ c8 ^ c4 ^ c2 ^ d8 ^ d2 ^ d; 265 | output[3] = a8 ^ a2 ^ a ^ b8 ^ b4 ^ b ^ c8 ^ c ^ d8 ^ d4 ^ d2; 266 | } 267 | 268 | /** @endcond */ 269 | 270 | void AESCommon::encryptBlock(uint8_t *output, const uint8_t *input) 271 | { 272 | const uint8_t *roundKey = schedule; 273 | uint8_t posn; 274 | uint8_t round; 275 | uint8_t state1[16]; 276 | uint8_t state2[16]; 277 | 278 | // Copy the input into the state and XOR with the first round key. 279 | for (posn = 0; posn < 16; ++posn) 280 | state1[posn] = input[posn] ^ roundKey[posn]; 281 | roundKey += 16; 282 | 283 | // Perform all rounds except the last. 284 | for (round = rounds; round > 1; --round) { 285 | subBytesAndShiftRows(state2, state1); 286 | mixColumn(state1, state2); 287 | mixColumn(state1 + 4, state2 + 4); 288 | mixColumn(state1 + 8, state2 + 8); 289 | mixColumn(state1 + 12, state2 + 12); 290 | for (posn = 0; posn < 16; ++posn) 291 | state1[posn] ^= roundKey[posn]; 292 | roundKey += 16; 293 | } 294 | 295 | // Perform the final round. 296 | subBytesAndShiftRows(state2, state1); 297 | for (posn = 0; posn < 16; ++posn) 298 | output[posn] = state2[posn] ^ roundKey[posn]; 299 | } 300 | 301 | void AESCommon::decryptBlock(uint8_t *output, const uint8_t *input) 302 | { 303 | const uint8_t *roundKey = schedule + rounds * 16; 304 | uint8_t round; 305 | uint8_t posn; 306 | uint8_t state1[16]; 307 | uint8_t state2[16]; 308 | 309 | // Copy the input into the state and reverse the final round. 310 | for (posn = 0; posn < 16; ++posn) 311 | state1[posn] = input[posn] ^ roundKey[posn]; 312 | inverseShiftRowsAndSubBytes(state2, state1); 313 | 314 | // Perform all other rounds in reverse. 315 | for (round = rounds; round > 1; --round) { 316 | roundKey -= 16; 317 | for (posn = 0; posn < 16; ++posn) 318 | state2[posn] ^= roundKey[posn]; 319 | inverseMixColumn(state1, state2); 320 | inverseMixColumn(state1 + 4, state2 + 4); 321 | inverseMixColumn(state1 + 8, state2 + 8); 322 | inverseMixColumn(state1 + 12, state2 + 12); 323 | inverseShiftRowsAndSubBytes(state2, state1); 324 | } 325 | 326 | // Reverse the initial round and create the output words. 327 | roundKey -= 16; 328 | for (posn = 0; posn < 16; ++posn) 329 | output[posn] = state2[posn] ^ roundKey[posn]; 330 | } 331 | 332 | void AESCommon::clear() 333 | { 334 | clean(schedule, (rounds + 1) * 16); 335 | } 336 | 337 | /** @cond aes_keycore */ 338 | 339 | void AESCommon::keyScheduleCore(uint8_t *output, const uint8_t *input, uint8_t iteration) 340 | { 341 | // Rcon(i), 2^i in the Rijndael finite field, for i = 0..10. 342 | // http://en.wikipedia.org/wiki/Rijndael_key_schedule 343 | static uint8_t const rcon[11] PROGMEM = { 344 | 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, // 0x00 345 | 0x80, 0x1B, 0x36 346 | }; 347 | output[0] = pgm_read_byte(sbox + input[1]) ^ pgm_read_byte(rcon + iteration); 348 | output[1] = pgm_read_byte(sbox + input[2]); 349 | output[2] = pgm_read_byte(sbox + input[3]); 350 | output[3] = pgm_read_byte(sbox + input[0]); 351 | } 352 | 353 | void AESCommon::applySbox(uint8_t *output, const uint8_t *input) 354 | { 355 | output[0] = pgm_read_byte(sbox + input[0]); 356 | output[1] = pgm_read_byte(sbox + input[1]); 357 | output[2] = pgm_read_byte(sbox + input[2]); 358 | output[3] = pgm_read_byte(sbox + input[3]); 359 | } 360 | 361 | /** @endcond */ 362 | 363 | #endif // CRYPTO_AES_DEFAULT 364 | -------------------------------------------------------------------------------- /src/libraries/aes/AESEsp32.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Southern Storm Software, Pty Ltd. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included 12 | * in all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #include "AES.h" 24 | #include "Crypto.h" 25 | #include 26 | 27 | // AES implementation for ESP32 using the hardware crypto module. 28 | 29 | #if defined(CRYPTO_AES_ESP32) 30 | 31 | // Declare the functions in the esp-idf SDK that we need. 32 | extern "C" { 33 | int esp_aes_setkey(unsigned char *ctx, const unsigned char *key, 34 | unsigned int keybits); 35 | int esp_aes_crypt_ecb(unsigned char *ctx, int mode, 36 | const unsigned char *input, 37 | unsigned char *output); 38 | }; 39 | 40 | AESCommon::AESCommon(uint8_t keySize) 41 | { 42 | memset(ctx, 0, sizeof(ctx)); 43 | ctx[0] = keySize; 44 | } 45 | 46 | AESCommon::~AESCommon() 47 | { 48 | clean(ctx, sizeof(ctx)); 49 | } 50 | 51 | size_t AESCommon::blockSize() const 52 | { 53 | return 16; 54 | } 55 | 56 | size_t AESCommon::keySize() const 57 | { 58 | return ctx[0]; 59 | } 60 | 61 | bool AESCommon::setKey(const uint8_t *key, size_t len) 62 | { 63 | if (len == ctx[0]) { 64 | esp_aes_setkey(ctx, key, len * 8); 65 | return true; 66 | } 67 | return false; 68 | } 69 | 70 | void AESCommon::encryptBlock(uint8_t *output, const uint8_t *input) 71 | { 72 | esp_aes_crypt_ecb(ctx, 1, input, output); 73 | } 74 | 75 | void AESCommon::decryptBlock(uint8_t *output, const uint8_t *input) 76 | { 77 | esp_aes_crypt_ecb(ctx, 0, input, output); 78 | } 79 | 80 | void AESCommon::clear() 81 | { 82 | uint8_t keySize = ctx[0]; 83 | clean(ctx, sizeof(ctx)); 84 | ctx[0] = keySize; 85 | } 86 | 87 | AES128::~AES128() 88 | { 89 | } 90 | 91 | AES192::~AES192() 92 | { 93 | } 94 | 95 | AES256::~AES256() 96 | { 97 | } 98 | 99 | #endif // CRYPTO_AES_ESP32 100 | -------------------------------------------------------------------------------- /src/libraries/aes/BlockCipher.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Southern Storm Software, Pty Ltd. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included 12 | * in all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #include "BlockCipher.h" 24 | 25 | /** 26 | * \class BlockCipher BlockCipher.h 27 | * \brief Abstract base class for block ciphers. 28 | * 29 | * Block ciphers always operate in electronic codebook (ECB) mode. 30 | * Higher-level classes such as CFB128 and CTR128 wrap the block cipher to 31 | * create more useful classes for encryption and decryption of bulk data. 32 | * 33 | * References: http://en.wikipedia.org/wiki/Block_cipher, 34 | * http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29 35 | */ 36 | 37 | /** 38 | * \brief Constructs a block cipher. 39 | */ 40 | BlockCipher::BlockCipher() 41 | { 42 | } 43 | 44 | /** 45 | * \brief Destroys this block cipher object. 46 | * 47 | * Subclasses are responsible for clearing temporary key schedules 48 | * and other buffers so as to avoid leaking sensitive information. 49 | * 50 | * \sa clear() 51 | */ 52 | BlockCipher::~BlockCipher() 53 | { 54 | } 55 | 56 | /** 57 | * \fn size_t BlockCipher::blockSize() const 58 | * \brief Size of a single block processed by this cipher, in bytes. 59 | * 60 | * \return Returns the size of a block in bytes. 61 | * 62 | * \sa keySize(), encryptBlock() 63 | */ 64 | 65 | /** 66 | * \fn size_t BlockCipher::keySize() const 67 | * \brief Default size of the key for this block cipher, in bytes. 68 | * 69 | * This value indicates the default, or recommended, size for the key. 70 | * 71 | * \sa setKey(), blockSize() 72 | */ 73 | 74 | /** 75 | * \fn bool BlockCipher::setKey(const uint8_t *key, size_t len) 76 | * \brief Sets the key to use for future encryption and decryption operations. 77 | * 78 | * \param key The key to use. 79 | * \param len The length of the key. 80 | * \return Returns false if the key length is not supported, or the key 81 | * is somehow "weak" and unusable by this cipher. 82 | * 83 | * Use clear() or the destructor to remove the key and any other sensitive 84 | * data from the object once encryption or decryption is complete. 85 | * 86 | * \sa keySize(), clear() 87 | */ 88 | 89 | /** 90 | * \fn void BlockCipher::encryptBlock(uint8_t *output, const uint8_t *input) 91 | * \brief Encrypts a single block using this cipher. 92 | * 93 | * \param output The output buffer to put the ciphertext into. 94 | * Must be at least blockSize() bytes in length. 95 | * \param input The input buffer to read the plaintext from which is 96 | * allowed to overlap with \a output. Must be at least blockSize() 97 | * bytes in length. 98 | * 99 | * \sa decryptBlock(), blockSize() 100 | */ 101 | 102 | /** 103 | * \fn void BlockCipher::decryptBlock(uint8_t *output, const uint8_t *input) 104 | * \brief Decrypts a single block using this cipher. 105 | * 106 | * \param output The output buffer to put the plaintext into. 107 | * Must be at least blockSize() bytes in length. 108 | * \param input The input buffer to read the ciphertext from which is 109 | * allowed to overlap with \a output. Must be at least blockSize() 110 | * bytes in length. 111 | * 112 | * \sa encryptBlock(), blockSize() 113 | */ 114 | 115 | /** 116 | * \fn void BlockCipher::clear() 117 | * \brief Clears all security-sensitive state from this block cipher. 118 | * 119 | * Security-sensitive information includes key schedules and any 120 | * temporary state that is used by encryptBlock() or decryptBlock() 121 | * which is stored in the object itself. 122 | * 123 | * \sa setKey(), encryptBlock(), decryptBlock() 124 | */ 125 | -------------------------------------------------------------------------------- /src/libraries/aes/BlockCipher.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Southern Storm Software, Pty Ltd. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included 12 | * in all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef CRYPTO_BLOCKCIPHER_h 24 | #define CRYPTO_BLOCKCIPHER_h 25 | 26 | #include 27 | #include 28 | 29 | class BlockCipher 30 | { 31 | public: 32 | BlockCipher(); 33 | virtual ~BlockCipher(); 34 | 35 | virtual size_t blockSize() const = 0; 36 | virtual size_t keySize() const = 0; 37 | 38 | virtual bool setKey(const uint8_t *key, size_t len) = 0; 39 | 40 | virtual void encryptBlock(uint8_t *output, const uint8_t *input) = 0; 41 | virtual void decryptBlock(uint8_t *output, const uint8_t *input) = 0; 42 | 43 | virtual void clear() = 0; 44 | }; 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /src/libraries/aes/CBC.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Southern Storm Software, Pty Ltd. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included 12 | * in all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #include "CBC.h" 24 | #include "Crypto.h" 25 | #include 26 | 27 | /** 28 | * \class CBCCommon CBC.h 29 | * \brief Concrete base class to assist with implementing CBC for 30 | * 128-bit block ciphers. 31 | * 32 | * Reference: http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation 33 | * 34 | * \sa CBC 35 | */ 36 | 37 | /** 38 | * \brief Constructs a new cipher in CBC mode. 39 | * 40 | * This constructor should be followed by a call to setBlockCipher(). 41 | */ 42 | CBCCommon::CBCCommon() 43 | : blockCipher(0) 44 | , posn(16) 45 | { 46 | } 47 | 48 | /** 49 | * \brief Destroys this cipher object after clearing sensitive information. 50 | */ 51 | CBCCommon::~CBCCommon() 52 | { 53 | clean(iv); 54 | clean(temp); 55 | } 56 | 57 | size_t CBCCommon::keySize() const 58 | { 59 | return blockCipher->keySize(); 60 | } 61 | 62 | size_t CBCCommon::ivSize() const 63 | { 64 | return 16; 65 | } 66 | 67 | bool CBCCommon::setKey(const uint8_t *key, size_t len) 68 | { 69 | // Verify the cipher's block size, just in case. 70 | if (blockCipher->blockSize() != 16) 71 | return false; 72 | 73 | // Set the key on the underlying block cipher. 74 | return blockCipher->setKey(key, len); 75 | } 76 | 77 | bool CBCCommon::setIV(const uint8_t *iv, size_t len) 78 | { 79 | if (len != 16) 80 | return false; 81 | memcpy(this->iv, iv, 16); 82 | posn = 16; 83 | return true; 84 | } 85 | 86 | void CBCCommon::encrypt(uint8_t *output, const uint8_t *input, size_t len) 87 | { 88 | uint8_t posn; 89 | while (len >= 16) { 90 | for (posn = 0; posn < 16; ++posn) 91 | iv[posn] ^= *input++; 92 | blockCipher->encryptBlock(iv, iv); 93 | for (posn = 0; posn < 16; ++posn) 94 | *output++ = iv[posn]; 95 | len -= 16; 96 | } 97 | } 98 | 99 | void CBCCommon::decrypt(uint8_t *output, const uint8_t *input, size_t len) 100 | { 101 | uint8_t posn; 102 | while (len >= 16) { 103 | blockCipher->decryptBlock(temp, input); 104 | for (posn = 0; posn < 16; ++posn) { 105 | uint8_t in = *input++; 106 | *output++ = temp[posn] ^ iv[posn]; 107 | iv[posn] = in; 108 | } 109 | len -= 16; 110 | } 111 | } 112 | 113 | void CBCCommon::clear() 114 | { 115 | blockCipher->clear(); 116 | clean(iv); 117 | clean(temp); 118 | posn = 16; 119 | } 120 | 121 | /** 122 | * \fn void CBCCommon::setBlockCipher(BlockCipher *cipher) 123 | * \brief Sets the block cipher to use for this CBC object. 124 | * 125 | * \param cipher The block cipher to use to implement CBC mode, 126 | * which must have a block size of 16 bytes (128 bits). 127 | */ 128 | 129 | /** 130 | * \class CBC CBC.h 131 | * \brief Implementation of the Cipher Block Chaining (CBC) mode for 132 | * 128-bit block ciphers. 133 | * 134 | * The template parameter T must be a concrete subclass of BlockCipher 135 | * indicating the specific block cipher to use. T must have a block size 136 | * of 16 bytes (128 bits). 137 | * 138 | * For example, the following creates a CBC object using AES192 as the 139 | * underlying cipher: 140 | * 141 | * \code 142 | * CBC cbc; 143 | * cbc.setKey(key, 24); 144 | * cbc.setIV(iv, 16); 145 | * cbc.encrypt(output, input, len); 146 | * \endcode 147 | * 148 | * Decryption is similar: 149 | * 150 | * \code 151 | * CBC cbc; 152 | * cbc.setKey(key, 24); 153 | * cbc.setIV(iv, 16); 154 | * cbc.decrypt(output, input, len); 155 | * \endcode 156 | * 157 | * The size of the ciphertext will always be the same as the size of 158 | * the plaintext. Also, the length of the plaintext/ciphertext must be a 159 | * multiple of 16. Extra bytes are ignored and not encrypted. The caller 160 | * is responsible for padding the underlying data to a multiple of 16 161 | * using an appropriate padding scheme for the application. 162 | * 163 | * Reference: http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation 164 | * 165 | * \sa CTR, CFB, OFB 166 | */ 167 | 168 | /** 169 | * \fn CBC::CBC() 170 | * \brief Constructs a new CBC object for the block cipher T. 171 | */ 172 | -------------------------------------------------------------------------------- /src/libraries/aes/CBC.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Southern Storm Software, Pty Ltd. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included 12 | * in all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef CRYPTO_CBC_h 24 | #define CRYPTO_CBC_h 25 | 26 | #include "Cipher.h" 27 | #include "BlockCipher.h" 28 | 29 | class CBCCommon : public Cipher 30 | { 31 | public: 32 | virtual ~CBCCommon(); 33 | 34 | size_t keySize() const; 35 | size_t ivSize() const; 36 | 37 | bool setKey(const uint8_t *key, size_t len); 38 | bool setIV(const uint8_t *iv, size_t len); 39 | 40 | void encrypt(uint8_t *output, const uint8_t *input, size_t len); 41 | void decrypt(uint8_t *output, const uint8_t *input, size_t len); 42 | 43 | void clear(); 44 | 45 | protected: 46 | CBCCommon(); 47 | void setBlockCipher(BlockCipher *cipher) { blockCipher = cipher; } 48 | 49 | private: 50 | BlockCipher *blockCipher; 51 | uint8_t iv[16]; 52 | uint8_t temp[16]; 53 | uint8_t posn; 54 | }; 55 | 56 | template 57 | class CBC : public CBCCommon 58 | { 59 | public: 60 | CBC() { setBlockCipher(&cipher); } 61 | 62 | private: 63 | T cipher; 64 | }; 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /src/libraries/aes/Cipher.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Southern Storm Software, Pty Ltd. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included 12 | * in all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #include "Cipher.h" 24 | 25 | /** 26 | * \class Cipher Cipher.h 27 | * \brief Abstract base class for stream ciphers. 28 | * 29 | * This class is intended for implementing ciphers that operate on arbitrary 30 | * amounts of data. In particular, stream ciphers where the number of 31 | * bytes that are input to encrypt() or decrypt() is exactly the same as 32 | * the number of bytes that are output. 33 | * 34 | * All of the stream ciphers such as ChaCha inherit directly from this class, 35 | * together with block cipher modes such as CTR and CFB. 36 | */ 37 | 38 | /** 39 | * \brief Constructs a new cipher object. 40 | */ 41 | Cipher::Cipher() 42 | { 43 | } 44 | 45 | /** 46 | * \brief Destroys this cipher object. 47 | * 48 | * Subclasses are responsible for clearing temporary key schedules 49 | * and other buffers so as to avoid leaking sensitive information. 50 | * 51 | * \sa clear() 52 | */ 53 | Cipher::~Cipher() 54 | { 55 | } 56 | 57 | /** 58 | * \fn size_t Cipher::keySize() const 59 | * \brief Default size of the key for this cipher, in bytes. 60 | * 61 | * If the cipher supports variable-sized keys, keySize() indicates the 62 | * default or recommended key size. The cipher may support other key sizes. 63 | * 64 | * \sa setKey(), ivSize() 65 | */ 66 | 67 | /** 68 | * \fn size_t Cipher::ivSize() const 69 | * \brief Size of the initialization vector for this cipher, in bytes. 70 | * 71 | * If the cipher does not need an initialization vector, this function 72 | * will return zero. 73 | */ 74 | 75 | /** 76 | * \fn bool Cipher::setKey(const uint8_t *key, size_t len) 77 | * \brief Sets the key to use for future encryption and decryption operations. 78 | * 79 | * \param key The key to use. 80 | * \param len The length of the key in bytes. 81 | * \return Returns false if the key length is not supported, or the key 82 | * is somehow "weak" and unusable by this cipher. 83 | * 84 | * Use clear() or the destructor to remove the key and any other sensitive 85 | * data from the object once encryption or decryption is complete. 86 | * 87 | * Calling setKey() resets the cipher. Any temporary data that was being 88 | * retained for encrypting partial blocks will be abandoned. 89 | * 90 | * \sa keySize(), clear() 91 | */ 92 | 93 | /** 94 | * \fn bool Cipher::setIV(const uint8_t *iv, size_t len) 95 | * \brief Sets the initialization vector to use for future encryption and 96 | * decryption operations. 97 | * 98 | * \param iv The initialization vector to use. 99 | * \param len The length of the initialization vector in bytes. 100 | * \return Returns false if the length is not supported. 101 | * 102 | * Initialization vectors should be set before the first call to 103 | * encrypt() or decrypt() after a setKey() call. If the initialization 104 | * vector is changed after encryption or decryption begins, 105 | * then the behaviour is undefined. 106 | * 107 | * \note The IV is not encoded into the output stream by encrypt(). 108 | * The caller is responsible for communicating the IV to the other party. 109 | * 110 | * \sa ivSize() 111 | */ 112 | 113 | /** 114 | * \fn void Cipher::encrypt(uint8_t *output, const uint8_t *input, size_t len) 115 | * \brief Encrypts an input buffer and writes the ciphertext to an 116 | * output buffer. 117 | * 118 | * \param output The output buffer to write to, which may be the same 119 | * buffer as \a input. The \a output buffer must have at least as many 120 | * bytes as the \a input buffer. 121 | * \param input The input buffer to read from. 122 | * \param len The number of bytes to encrypt. 123 | * 124 | * The encrypt() function can be called multiple times with different 125 | * regions of the plaintext data. 126 | * 127 | * \sa decrypt() 128 | */ 129 | 130 | /** 131 | * \fn void Cipher::decrypt(uint8_t *output, const uint8_t *input, size_t len) 132 | * \brief Decrypts an input buffer and writes the plaintext to an 133 | * output buffer. 134 | * 135 | * \param output The output buffer to write to, which may be the same 136 | * buffer as \a input. The \a output buffer must have at least as many 137 | * bytes as the \a input buffer. 138 | * \param input The input buffer to read from. 139 | * \param len The number of bytes to decrypt. 140 | * 141 | * The decrypt() function can be called multiple times with different 142 | * regions of the ciphertext data. 143 | * 144 | * \sa encrypt() 145 | */ 146 | 147 | /** 148 | * \fn void Cipher::clear() 149 | * \brief Clears all security-sensitive state from this cipher. 150 | * 151 | * Security-sensitive information includes key schedules, initialization 152 | * vectors, and any temporary state that is used by encrypt() or decrypt() 153 | * which is stored in the cipher itself. 154 | */ 155 | -------------------------------------------------------------------------------- /src/libraries/aes/Cipher.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Southern Storm Software, Pty Ltd. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included 12 | * in all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef CRYPTO_CIPHER_h 24 | #define CRYPTO_CIPHER_h 25 | 26 | #include 27 | #include 28 | 29 | class Cipher 30 | { 31 | public: 32 | Cipher(); 33 | virtual ~Cipher(); 34 | 35 | virtual size_t keySize() const = 0; 36 | virtual size_t ivSize() const = 0; 37 | 38 | virtual bool setKey(const uint8_t *key, size_t len) = 0; 39 | virtual bool setIV(const uint8_t *iv, size_t len) = 0; 40 | 41 | virtual void encrypt(uint8_t *output, const uint8_t *input, size_t len) = 0; 42 | virtual void decrypt(uint8_t *output, const uint8_t *input, size_t len) = 0; 43 | 44 | virtual void clear() = 0; 45 | }; 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /src/libraries/aes/Crypto.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Southern Storm Software, Pty Ltd. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included 12 | * in all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #include "Crypto.h" 24 | 25 | /** 26 | * \brief Cleans a block of bytes. 27 | * 28 | * \param dest The destination block to be cleaned. 29 | * \param size The size of the destination to be cleaned in bytes. 30 | * 31 | * Unlike memset(), this function attempts to prevent the compiler 32 | * from optimizing away the clear on a memory buffer. 33 | */ 34 | void clean(void *dest, size_t size) 35 | { 36 | // Force the use of volatile so that we actually clear the memory. 37 | // Otherwise the compiler might optimise the entire contents of this 38 | // function away, which will not be secure. 39 | volatile uint8_t *d = (volatile uint8_t *)dest; 40 | while (size > 0) { 41 | *d++ = 0; 42 | --size; 43 | } 44 | } 45 | 46 | /** 47 | * \fn void clean(T &var) 48 | * \brief Template function that cleans a variable. 49 | * 50 | * \param var A reference to the variable to clean. 51 | * 52 | * The variable will be cleared to all-zeroes in a secure manner. 53 | * Unlike memset(), this function attempts to prevent the compiler 54 | * from optimizing away the variable clear. 55 | */ 56 | 57 | /** 58 | * \brief Compares two memory blocks for equality. 59 | * 60 | * \param data1 Points to the first memory block. 61 | * \param data2 Points to the second memory block. 62 | * \param len The size of the memory blocks in bytes. 63 | * 64 | * Unlike memcmp(), this function attempts to compare the two memory blocks 65 | * in a way that will not reveal the contents in the instruction timing. 66 | * In particular, this function will not stop early if a byte is different. 67 | * It will instead continue onto the end of the array. 68 | */ 69 | bool secure_compare(const void *data1, const void *data2, size_t len) 70 | { 71 | uint8_t result = 0; 72 | const uint8_t *d1 = (const uint8_t *)data1; 73 | const uint8_t *d2 = (const uint8_t *)data2; 74 | while (len > 0) { 75 | result |= (*d1++ ^ *d2++); 76 | --len; 77 | } 78 | return (bool)((((uint16_t)0x0100) - result) >> 8); 79 | } 80 | 81 | /** 82 | * \brief Calculates the CRC-8 value over an array in memory. 83 | * 84 | * \param tag Starting tag to distinguish this calculation. 85 | * \param data The data to checksum. 86 | * \param size The number of bytes to checksum. 87 | * \return The CRC-8 value over the data. 88 | * 89 | * This function does not provide any real security. It is a simple 90 | * check that seed values have been initialized within EEPROM or Flash. 91 | * If the CRC-8 check fails, then it is assumed that the EEPROM/Flash 92 | * contents are invalid and should be re-initialized. 93 | * 94 | * Reference: http://www.sunshine2k.de/articles/coding/crc/understanding_crc.html#ch4 95 | */ 96 | uint8_t crypto_crc8(uint8_t tag, const void *data, unsigned size) 97 | { 98 | const uint8_t *d = (const uint8_t *)data; 99 | uint8_t crc = 0xFF ^ tag; 100 | uint8_t bit; 101 | while (size > 0) { 102 | crc ^= *d++; 103 | for (bit = 0; bit < 8; ++bit) { 104 | // if (crc & 0x80) 105 | // crc = (crc << 1) ^ 0x1D; 106 | // else 107 | // crc = (crc << 1); 108 | uint8_t generator = (uint8_t)((((int8_t)crc) >> 7) & 0x1D); 109 | crc = (crc << 1) ^ generator; 110 | } 111 | --size; 112 | } 113 | return crc; 114 | } 115 | -------------------------------------------------------------------------------- /src/libraries/aes/Crypto.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Southern Storm Software, Pty Ltd. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included 12 | * in all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef CRYPTO_h 24 | #define CRYPTO_h 25 | 26 | #include 27 | #include 28 | 29 | void clean(void *dest, size_t size); 30 | 31 | template 32 | inline void clean(T &var) 33 | { 34 | clean(&var, sizeof(T)); 35 | } 36 | 37 | bool secure_compare(const void *data1, const void *data2, size_t len); 38 | 39 | #if defined(ESP8266) 40 | extern "C" void system_soft_wdt_feed(void); 41 | #define crypto_feed_watchdog() system_soft_wdt_feed() 42 | #else 43 | #define crypto_feed_watchdog() do { ; } while (0) 44 | #endif 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /src/libraries/aes/utility/EndianUtil.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Southern Storm Software, Pty Ltd. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included 12 | * in all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef CRYPTO_ENDIANUTIL_H 24 | #define CRYPTO_ENDIANUTIL_H 25 | 26 | #include 27 | 28 | #if !defined(HOST_BUILD) 29 | 30 | // CPU is assumed to be little endian. Edit this file if you 31 | // need to port this library to a big endian CPU. 32 | 33 | #define CRYPTO_LITTLE_ENDIAN 1 34 | 35 | #define htole16(x) (x) 36 | #define le16toh(x) (x) 37 | #define htobe16(x) \ 38 | (__extension__ ({ \ 39 | uint16_t _temp = (x); \ 40 | ((_temp >> 8) & 0x00FF) | \ 41 | ((_temp << 8) & 0xFF00); \ 42 | })) 43 | #define be16toh(x) (htobe16((x))) 44 | 45 | #define htole32(x) (x) 46 | #define le32toh(x) (x) 47 | #define htobe32(x) \ 48 | (__extension__ ({ \ 49 | uint32_t _temp = (x); \ 50 | ((_temp >> 24) & 0x000000FF) | \ 51 | ((_temp >> 8) & 0x0000FF00) | \ 52 | ((_temp << 8) & 0x00FF0000) | \ 53 | ((_temp << 24) & 0xFF000000); \ 54 | })) 55 | #define be32toh(x) (htobe32((x))) 56 | 57 | #define htole64(x) (x) 58 | #define le64toh(x) (x) 59 | #define htobe64(x) \ 60 | (__extension__ ({ \ 61 | uint64_t __temp = (x); \ 62 | uint32_t __low = htobe32((uint32_t)__temp); \ 63 | uint32_t __high = htobe32((uint32_t)(__temp >> 32)); \ 64 | (((uint64_t)__low) << 32) | __high; \ 65 | })) 66 | #define be64toh(x) (htobe64((x))) 67 | 68 | #else // HOST_BUILD 69 | 70 | #include 71 | #if __BYTE_ORDER == __LITTLE_ENDIAN 72 | #define CRYPTO_LITTLE_ENDIAN 1 73 | #endif 74 | 75 | #endif // HOST_BUILD 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /src/libraries/aes/utility/LimbUtil.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Southern Storm Software, Pty Ltd. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included 12 | * in all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef CRYPTO_LIMBUTIL_H 24 | #define CRYPTO_LIMBUTIL_H 25 | 26 | #include "ProgMemUtil.h" 27 | 28 | // Number of limbs in a big number value of various sizes. 29 | #define NUM_LIMBS_BITS(n) \ 30 | (((n) + sizeof(limb_t) * 8 - 1) / (8 * sizeof(limb_t))) 31 | #define NUM_LIMBS_128BIT NUM_LIMBS_BITS(128) 32 | #define NUM_LIMBS_256BIT NUM_LIMBS_BITS(256) 33 | #define NUM_LIMBS_512BIT NUM_LIMBS_BITS(512) 34 | 35 | // The number of bits in a limb. 36 | #define LIMB_BITS (8 * sizeof(limb_t)) 37 | 38 | // Read a limb-sized quantity from program memory. 39 | #if BIGNUMBER_LIMB_8BIT 40 | #define pgm_read_limb(x) (pgm_read_byte((x))) 41 | #elif BIGNUMBER_LIMB_16BIT 42 | #define pgm_read_limb(x) (pgm_read_word((x))) 43 | #elif BIGNUMBER_LIMB_32BIT 44 | #define pgm_read_limb(x) (pgm_read_dword((x))) 45 | #elif BIGNUMBER_LIMB_64BIT 46 | #define pgm_read_limb(x) (pgm_read_qword((x))) 47 | #endif 48 | 49 | // Expand a 32-bit value into a set of limbs depending upon the limb size. 50 | // This is used when initializing constant big number values in the code. 51 | // For 64-bit system compatibility it is necessary to use LIMB_PAIR(x, y). 52 | #if BIGNUMBER_LIMB_8BIT 53 | #define LIMB(value) ((uint8_t)(value)), \ 54 | ((uint8_t)((value) >> 8)), \ 55 | ((uint8_t)((value) >> 16)), \ 56 | ((uint8_t)((value) >> 24)) 57 | #define LIMB_PAIR(x,y) LIMB((x)), LIMB((y)) 58 | #elif BIGNUMBER_LIMB_16BIT 59 | #define LIMB(value) ((uint16_t)(value)), \ 60 | ((uint16_t)(((uint32_t)(value)) >> 16)) 61 | #define LIMB_PAIR(x,y) LIMB((x)), LIMB((y)) 62 | #elif BIGNUMBER_LIMB_32BIT 63 | #define LIMB(value) (value) 64 | #define LIMB_PAIR(x,y) LIMB((x)), LIMB((y)) 65 | #elif BIGNUMBER_LIMB_64BIT 66 | #define LIMB(value) (value) 67 | #define LIMB_PAIR(x,y) ((((uint64_t)(y)) << 32) | ((uint64_t)(x))) 68 | #endif 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /src/libraries/aes/utility/ProgMemUtil.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Southern Storm Software, Pty Ltd. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included 12 | * in all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef CRYPTO_PROGMEMUTIL_H 24 | #define CRYPTO_PROGMEMUTIL_H 25 | 26 | #if defined(__AVR__) 27 | #include 28 | #define pgm_read_qword(x) \ 29 | (__extension__ ({ \ 30 | const uint32_t *_temp = (const uint32_t *)(x); \ 31 | ((uint64_t)pgm_read_dword(_temp)) | \ 32 | (((uint64_t)pgm_read_dword(_temp + 1)) << 32); \ 33 | })) 34 | #elif defined(ESP8266) || defined(ESP32) 35 | #include 36 | #define pgm_read_qword(x) \ 37 | (__extension__ ({ \ 38 | const uint32_t *_temp = (const uint32_t *)(x); \ 39 | ((uint64_t)pgm_read_dword(_temp)) | \ 40 | (((uint64_t)pgm_read_dword(_temp + 1)) << 32); \ 41 | })) 42 | #else 43 | #include 44 | #define PROGMEM 45 | #ifndef pgm_read_byte 46 | # define pgm_read_byte(x) (*(x)) 47 | #endif 48 | #ifndef pgm_read_word 49 | # define pgm_read_word(x) (*(x)) 50 | #endif 51 | #ifndef pgm_read_dword 52 | # define pgm_read_dword(x) (*(x)) 53 | #endif 54 | #ifndef pgm_read_qword 55 | # define pgm_read_qword(x) (*(x)) 56 | #endif 57 | #ifndef memcpy_P 58 | # define memcpy_P(d,s,l) memcpy((d), (s), (l)) 59 | #endif 60 | #endif 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /src/libraries/aes/utility/RotateUtil_2.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Southern Storm Software, Pty Ltd. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included 12 | * in all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef CRYPTO_ROTATEUTIL_H 24 | #define CRYPTO_ROTATEUTIL_H 25 | 26 | #include 27 | 28 | // Rotation functions that are optimised for best performance on AVR. 29 | // The most efficient rotations are where the number of bits is 1 or a 30 | // multiple of 8, so we compose the efficient rotations to produce all 31 | // other rotation counts of interest. 32 | 33 | #if defined(__AVR__) 34 | #define CRYPTO_ROTATE32_COMPOSED 1 35 | #define CRYPTO_ROTATE64_COMPOSED 0 36 | #else 37 | #define CRYPTO_ROTATE32_COMPOSED 0 38 | #define CRYPTO_ROTATE64_COMPOSED 0 39 | #endif 40 | 41 | #if CRYPTO_ROTATE32_COMPOSED 42 | 43 | // Rotation macros for 32-bit arguments. 44 | 45 | // Generic left rotate - best performance when "bits" is 1 or a multiple of 8. 46 | #define leftRotate(a, bits) \ 47 | (__extension__ ({ \ 48 | uint32_t _temp = (a); \ 49 | (_temp << (bits)) | (_temp >> (32 - (bits))); \ 50 | })) 51 | 52 | // Generic right rotate - best performance when "bits" is 1 or a multiple of 8. 53 | #define rightRotate(a, bits) \ 54 | (__extension__ ({ \ 55 | uint32_t _temp = (a); \ 56 | (_temp >> (bits)) | (_temp << (32 - (bits))); \ 57 | })) 58 | 59 | // Left rotate by 1. 60 | #define leftRotate1(a) (leftRotate((a), 1)) 61 | 62 | // Left rotate by 2. 63 | #define leftRotate2(a) (leftRotate(leftRotate((a), 1), 1)) 64 | 65 | // Left rotate by 3. 66 | #define leftRotate3(a) (leftRotate(leftRotate(leftRotate((a), 1), 1), 1)) 67 | 68 | // Left rotate by 4. 69 | #define leftRotate4(a) (leftRotate(leftRotate(leftRotate(leftRotate((a), 1), 1), 1), 1)) 70 | 71 | // Left rotate by 5: Rotate left by 8, then right by 3. 72 | #define leftRotate5(a) (rightRotate(rightRotate(rightRotate(leftRotate((a), 8), 1), 1), 1)) 73 | 74 | // Left rotate by 6: Rotate left by 8, then right by 2. 75 | #define leftRotate6(a) (rightRotate(rightRotate(leftRotate((a), 8), 1), 1)) 76 | 77 | // Left rotate by 7: Rotate left by 8, then right by 1. 78 | #define leftRotate7(a) (rightRotate(leftRotate((a), 8), 1)) 79 | 80 | // Left rotate by 8. 81 | #define leftRotate8(a) (leftRotate((a), 8)) 82 | 83 | // Left rotate by 9: Rotate left by 8, then left by 1. 84 | #define leftRotate9(a) (leftRotate(leftRotate((a), 8), 1)) 85 | 86 | // Left rotate by 10: Rotate left by 8, then left by 2. 87 | #define leftRotate10(a) (leftRotate(leftRotate(leftRotate((a), 8), 1), 1)) 88 | 89 | // Left rotate by 11: Rotate left by 8, then left by 3. 90 | #define leftRotate11(a) (leftRotate(leftRotate(leftRotate(leftRotate((a), 8), 1), 1), 1)) 91 | 92 | // Left rotate by 12: Rotate left by 16, then right by 4. 93 | #define leftRotate12(a) (rightRotate(rightRotate(rightRotate(rightRotate(leftRotate((a), 16), 1), 1), 1), 1)) 94 | 95 | // Left rotate by 13: Rotate left by 16, then right by 3. 96 | #define leftRotate13(a) (rightRotate(rightRotate(rightRotate(leftRotate((a), 16), 1), 1), 1)) 97 | 98 | // Left rotate by 14: Rotate left by 16, then right by 2. 99 | #define leftRotate14(a) (rightRotate(rightRotate(leftRotate((a), 16), 1), 1)) 100 | 101 | // Left rotate by 15: Rotate left by 16, then right by 1. 102 | #define leftRotate15(a) (rightRotate(leftRotate((a), 16), 1)) 103 | 104 | // Left rotate by 16. 105 | #define leftRotate16(a) (leftRotate((a), 16)) 106 | 107 | // Left rotate by 17: Rotate left by 16, then left by 1. 108 | #define leftRotate17(a) (leftRotate(leftRotate((a), 16), 1)) 109 | 110 | // Left rotate by 18: Rotate left by 16, then left by 2. 111 | #define leftRotate18(a) (leftRotate(leftRotate(leftRotate((a), 16), 1), 1)) 112 | 113 | // Left rotate by 19: Rotate left by 16, then left by 3. 114 | #define leftRotate19(a) (leftRotate(leftRotate(leftRotate(leftRotate((a), 16), 1), 1), 1)) 115 | 116 | // Left rotate by 20: Rotate left by 16, then left by 4. 117 | #define leftRotate20(a) (leftRotate(leftRotate(leftRotate(leftRotate(leftRotate((a), 16), 1), 1), 1), 1)) 118 | 119 | // Left rotate by 21: Rotate left by 24, then right by 3. 120 | #define leftRotate21(a) (rightRotate(rightRotate(rightRotate(leftRotate((a), 24), 1), 1), 1)) 121 | 122 | // Left rotate by 22: Rotate left by 24, then right by 2. 123 | #define leftRotate22(a) (rightRotate(rightRotate(leftRotate((a), 24), 1), 1)) 124 | 125 | // Left rotate by 23: Rotate left by 24, then right by 1. 126 | #define leftRotate23(a) (rightRotate(leftRotate((a), 24), 1)) 127 | 128 | // Left rotate by 24. 129 | #define leftRotate24(a) (leftRotate((a), 24)) 130 | 131 | // Left rotate by 25: Rotate left by 24, then left by 1. 132 | #define leftRotate25(a) (leftRotate(leftRotate((a), 24), 1)) 133 | 134 | // Left rotate by 26: Rotate left by 24, then left by 2. 135 | #define leftRotate26(a) (leftRotate(leftRotate(leftRotate((a), 24), 1), 1)) 136 | 137 | // Left rotate by 27: Rotate left by 24, then left by 3. 138 | #define leftRotate27(a) (leftRotate(leftRotate(leftRotate(leftRotate((a), 24), 1), 1), 1)) 139 | 140 | // Left rotate by 28: Rotate right by 4. 141 | #define leftRotate28(a) (rightRotate(rightRotate(rightRotate(rightRotate((a), 1), 1), 1), 1)) 142 | 143 | // Left rotate by 29: Rotate right by 3. 144 | #define leftRotate29(a) (rightRotate(rightRotate(rightRotate((a), 1), 1), 1)) 145 | 146 | // Left rotate by 30: Rotate right by 2. 147 | #define leftRotate30(a) (rightRotate(rightRotate((a), 1), 1)) 148 | 149 | // Left rotate by 31: Rotate right by 1. 150 | #define leftRotate31(a) (rightRotate((a), 1)) 151 | 152 | // Define the 32-bit right rotations in terms of left rotations. 153 | #define rightRotate1(a) (leftRotate31((a))) 154 | #define rightRotate2(a) (leftRotate30((a))) 155 | #define rightRotate3(a) (leftRotate29((a))) 156 | #define rightRotate4(a) (leftRotate28((a))) 157 | #define rightRotate5(a) (leftRotate27((a))) 158 | #define rightRotate6(a) (leftRotate26((a))) 159 | #define rightRotate7(a) (leftRotate25((a))) 160 | #define rightRotate8(a) (leftRotate24((a))) 161 | #define rightRotate9(a) (leftRotate23((a))) 162 | #define rightRotate10(a) (leftRotate22((a))) 163 | #define rightRotate11(a) (leftRotate21((a))) 164 | #define rightRotate12(a) (leftRotate20((a))) 165 | #define rightRotate13(a) (leftRotate19((a))) 166 | #define rightRotate14(a) (leftRotate18((a))) 167 | #define rightRotate15(a) (leftRotate17((a))) 168 | #define rightRotate16(a) (leftRotate16((a))) 169 | #define rightRotate17(a) (leftRotate15((a))) 170 | #define rightRotate18(a) (leftRotate14((a))) 171 | #define rightRotate19(a) (leftRotate13((a))) 172 | #define rightRotate20(a) (leftRotate12((a))) 173 | #define rightRotate21(a) (leftRotate11((a))) 174 | #define rightRotate22(a) (leftRotate10((a))) 175 | #define rightRotate23(a) (leftRotate9((a))) 176 | #define rightRotate24(a) (leftRotate8((a))) 177 | #define rightRotate25(a) (leftRotate7((a))) 178 | #define rightRotate26(a) (leftRotate6((a))) 179 | #define rightRotate27(a) (leftRotate5((a))) 180 | #define rightRotate28(a) (leftRotate4((a))) 181 | #define rightRotate29(a) (leftRotate3((a))) 182 | #define rightRotate30(a) (leftRotate2((a))) 183 | #define rightRotate31(a) (leftRotate1((a))) 184 | 185 | #else // !CRYPTO_ROTATE32_COMPOSED 186 | 187 | // Generic rotation functions. All bit shifts are considered to have 188 | // similar performance. Usually true of 32-bit and higher platforms. 189 | 190 | // Rotation macros for 32-bit arguments. 191 | 192 | // Generic left rotate. 193 | #define leftRotate(a, bits) \ 194 | (__extension__ ({ \ 195 | uint32_t _temp = (a); \ 196 | (_temp << (bits)) | (_temp >> (32 - (bits))); \ 197 | })) 198 | 199 | // Generic right rotate. 200 | #define rightRotate(a, bits) \ 201 | (__extension__ ({ \ 202 | uint32_t _temp = (a); \ 203 | (_temp >> (bits)) | (_temp << (32 - (bits))); \ 204 | })) 205 | 206 | // Left rotate by a specific number of bits. 207 | #define leftRotate1(a) (leftRotate((a), 1)) 208 | #define leftRotate2(a) (leftRotate((a), 2)) 209 | #define leftRotate3(a) (leftRotate((a), 3)) 210 | #define leftRotate4(a) (leftRotate((a), 4)) 211 | #define leftRotate5(a) (leftRotate((a), 5)) 212 | #define leftRotate6(a) (leftRotate((a), 6)) 213 | #define leftRotate7(a) (leftRotate((a), 7)) 214 | #define leftRotate8(a) (leftRotate((a), 8)) 215 | #define leftRotate9(a) (leftRotate((a), 9)) 216 | #define leftRotate10(a) (leftRotate((a), 10)) 217 | #define leftRotate11(a) (leftRotate((a), 11)) 218 | #define leftRotate12(a) (leftRotate((a), 12)) 219 | #define leftRotate13(a) (leftRotate((a), 13)) 220 | #define leftRotate14(a) (leftRotate((a), 14)) 221 | #define leftRotate15(a) (leftRotate((a), 15)) 222 | #define leftRotate16(a) (leftRotate((a), 16)) 223 | #define leftRotate17(a) (leftRotate((a), 17)) 224 | #define leftRotate18(a) (leftRotate((a), 18)) 225 | #define leftRotate19(a) (leftRotate((a), 19)) 226 | #define leftRotate20(a) (leftRotate((a), 20)) 227 | #define leftRotate21(a) (leftRotate((a), 21)) 228 | #define leftRotate22(a) (leftRotate((a), 22)) 229 | #define leftRotate23(a) (leftRotate((a), 23)) 230 | #define leftRotate24(a) (leftRotate((a), 24)) 231 | #define leftRotate25(a) (leftRotate((a), 25)) 232 | #define leftRotate26(a) (leftRotate((a), 26)) 233 | #define leftRotate27(a) (leftRotate((a), 27)) 234 | #define leftRotate28(a) (leftRotate((a), 28)) 235 | #define leftRotate29(a) (leftRotate((a), 29)) 236 | #define leftRotate30(a) (leftRotate((a), 30)) 237 | #define leftRotate31(a) (leftRotate((a), 31)) 238 | 239 | // Right rotate by a specific number of bits. 240 | #define rightRotate1(a) (rightRotate((a), 1)) 241 | #define rightRotate2(a) (rightRotate((a), 2)) 242 | #define rightRotate3(a) (rightRotate((a), 3)) 243 | #define rightRotate4(a) (rightRotate((a), 4)) 244 | #define rightRotate5(a) (rightRotate((a), 5)) 245 | #define rightRotate6(a) (rightRotate((a), 6)) 246 | #define rightRotate7(a) (rightRotate((a), 7)) 247 | #define rightRotate8(a) (rightRotate((a), 8)) 248 | #define rightRotate9(a) (rightRotate((a), 9)) 249 | #define rightRotate10(a) (rightRotate((a), 10)) 250 | #define rightRotate11(a) (rightRotate((a), 11)) 251 | #define rightRotate12(a) (rightRotate((a), 12)) 252 | #define rightRotate13(a) (rightRotate((a), 13)) 253 | #define rightRotate14(a) (rightRotate((a), 14)) 254 | #define rightRotate15(a) (rightRotate((a), 15)) 255 | #define rightRotate16(a) (rightRotate((a), 16)) 256 | #define rightRotate17(a) (rightRotate((a), 17)) 257 | #define rightRotate18(a) (rightRotate((a), 18)) 258 | #define rightRotate19(a) (rightRotate((a), 19)) 259 | #define rightRotate20(a) (rightRotate((a), 20)) 260 | #define rightRotate21(a) (rightRotate((a), 21)) 261 | #define rightRotate22(a) (rightRotate((a), 22)) 262 | #define rightRotate23(a) (rightRotate((a), 23)) 263 | #define rightRotate24(a) (rightRotate((a), 24)) 264 | #define rightRotate25(a) (rightRotate((a), 25)) 265 | #define rightRotate26(a) (rightRotate((a), 26)) 266 | #define rightRotate27(a) (rightRotate((a), 27)) 267 | #define rightRotate28(a) (rightRotate((a), 28)) 268 | #define rightRotate29(a) (rightRotate((a), 29)) 269 | #define rightRotate30(a) (rightRotate((a), 30)) 270 | #define rightRotate31(a) (rightRotate((a), 31)) 271 | 272 | #endif // !CRYPTO_ROTATE32_COMPOSED 273 | 274 | #if CRYPTO_ROTATE64_COMPOSED 275 | 276 | // Rotation macros for 64-bit arguments. 277 | 278 | // Generic left rotate - best performance when "bits" is 1 or a multiple of 8. 279 | #define leftRotate_64(a, bits) \ 280 | (__extension__ ({ \ 281 | uint64_t _temp = (a); \ 282 | (_temp << (bits)) | (_temp >> (64 - (bits))); \ 283 | })) 284 | 285 | // Generic right rotate - best performance when "bits" is 1 or a multiple of 8. 286 | #define rightRotate_64(a, bits) \ 287 | (__extension__ ({ \ 288 | uint64_t _temp = (a); \ 289 | (_temp >> (bits)) | (_temp << (64 - (bits))); \ 290 | })) 291 | 292 | // Left rotate by 1. 293 | #define leftRotate1_64(a) (leftRotate_64((a), 1)) 294 | 295 | // Left rotate by 2. 296 | #define leftRotate2_64(a) (leftRotate_64(leftRotate_64((a), 1), 1)) 297 | 298 | // Left rotate by 3. 299 | #define leftRotate3_64(a) (leftRotate_64(leftRotate_64(leftRotate_64((a), 1), 1), 1)) 300 | 301 | // Left rotate by 4. 302 | #define leftRotate4_64(a) (leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64((a), 1), 1), 1), 1)) 303 | 304 | // Left rotate by 5: Rotate left by 8, then right by 3. 305 | #define leftRotate5_64(a) (rightRotate_64(rightRotate_64(rightRotate_64(leftRotate_64((a), 8), 1), 1), 1)) 306 | 307 | // Left rotate by 6: Rotate left by 8, then right by 2. 308 | #define leftRotate6_64(a) (rightRotate_64(rightRotate_64(leftRotate_64((a), 8), 1), 1)) 309 | 310 | // Left rotate by 7: Rotate left by 8, then right by 1. 311 | #define leftRotate7_64(a) (rightRotate_64(leftRotate_64((a), 8), 1)) 312 | 313 | // Left rotate by 8. 314 | #define leftRotate8_64(a) (leftRotate_64((a), 8)) 315 | 316 | // Left rotate by 9: Rotate left by 8, then left by 1. 317 | #define leftRotate9_64(a) (leftRotate_64(leftRotate_64((a), 8), 1)) 318 | 319 | // Left rotate by 10: Rotate left by 8, then left by 2. 320 | #define leftRotate10_64(a) (leftRotate_64(leftRotate_64(leftRotate_64((a), 8), 1), 1)) 321 | 322 | // Left rotate by 11: Rotate left by 8, then left by 3. 323 | #define leftRotate11_64(a) (leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64((a), 8), 1), 1), 1)) 324 | 325 | // Left rotate by 12: Rotate left by 16, then right by 4. 326 | #define leftRotate12_64(a) (rightRotate_64(rightRotate_64(rightRotate_64(rightRotate_64(leftRotate_64((a), 16), 1), 1), 1), 1)) 327 | 328 | // Left rotate by 13: Rotate left by 16, then right by 3. 329 | #define leftRotate13_64(a) (rightRotate_64(rightRotate_64(rightRotate_64(leftRotate_64((a), 16), 1), 1), 1)) 330 | 331 | // Left rotate by 14: Rotate left by 16, then right by 2. 332 | #define leftRotate14_64(a) (rightRotate_64(rightRotate_64(leftRotate_64((a), 16), 1), 1)) 333 | 334 | // Left rotate by 15: Rotate left by 16, then right by 1. 335 | #define leftRotate15_64(a) (rightRotate_64(leftRotate_64((a), 16), 1)) 336 | 337 | // Left rotate by 16. 338 | #define leftRotate16_64(a) (leftRotate_64((a), 16)) 339 | 340 | // Left rotate by 17: Rotate left by 16, then left by 1. 341 | #define leftRotate17_64(a) (leftRotate_64(leftRotate_64((a), 16), 1)) 342 | 343 | // Left rotate by 18: Rotate left by 16, then left by 2. 344 | #define leftRotate18_64(a) (leftRotate_64(leftRotate_64(leftRotate_64((a), 16), 1), 1)) 345 | 346 | // Left rotate by 19: Rotate left by 16, then left by 3. 347 | #define leftRotate19_64(a) (leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64((a), 16), 1), 1), 1)) 348 | 349 | // Left rotate by 20: Rotate left by 16, then left by 4. 350 | #define leftRotate20_64(a) (leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64((a), 16), 1), 1), 1), 1)) 351 | 352 | // Left rotate by 21: Rotate left by 24, then right by 3. 353 | #define leftRotate21_64(a) (rightRotate_64(rightRotate_64(rightRotate_64(leftRotate_64((a), 24), 1), 1), 1)) 354 | 355 | // Left rotate by 22: Rotate left by 24, then right by 2. 356 | #define leftRotate22_64(a) (rightRotate_64(rightRotate_64(leftRotate_64((a), 24), 1), 1)) 357 | 358 | // Left rotate by 23: Rotate left by 24, then right by 1. 359 | #define leftRotate23_64(a) (rightRotate_64(leftRotate_64((a), 24), 1)) 360 | 361 | // Left rotate by 24. 362 | #define leftRotate24_64(a) (leftRotate_64((a), 24)) 363 | 364 | // Left rotate by 25: Rotate left by 24, then left by 1. 365 | #define leftRotate25_64(a) (leftRotate_64(leftRotate_64((a), 24), 1)) 366 | 367 | // Left rotate by 26: Rotate left by 24, then left by 2. 368 | #define leftRotate26_64(a) (leftRotate_64(leftRotate_64(leftRotate_64((a), 24), 1), 1)) 369 | 370 | // Left rotate by 27: Rotate left by 24, then left by 3. 371 | #define leftRotate27_64(a) (leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64((a), 24), 1), 1), 1)) 372 | 373 | // Left rotate by 28: Rotate left by 24, then left by 4. 374 | #define leftRotate28_64(a) (leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64((a), 24), 1), 1), 1), 1)) 375 | 376 | // Left rotate by 29: Rotate left by 32, then right by 3. 377 | #define leftRotate29_64(a) (rightRotate_64(rightRotate_64(rightRotate_64(leftRotate_64((a), 32), 1), 1), 1)) 378 | 379 | // Left rotate by 30: Rotate left by 32, then right by 2. 380 | #define leftRotate30_64(a) (rightRotate_64(rightRotate_64(leftRotate_64((a), 32), 1), 1)) 381 | 382 | // Left rotate by 31: Rotate left by 32, then right by 1. 383 | #define leftRotate31_64(a) (rightRotate_64(leftRotate_64((a), 32), 1)) 384 | 385 | // Left rotate by 32. 386 | #define leftRotate32_64(a) (leftRotate_64((a), 32)) 387 | 388 | // Left rotate by 33: Rotate left by 32, then left by 1. 389 | #define leftRotate33_64(a) (leftRotate_64(leftRotate_64((a), 32), 1)) 390 | 391 | // Left rotate by 34: Rotate left by 32, then left by 2. 392 | #define leftRotate34_64(a) (leftRotate_64(leftRotate_64(leftRotate_64((a), 32), 1), 1)) 393 | 394 | // Left rotate by 35: Rotate left by 32, then left by 3. 395 | #define leftRotate35_64(a) (leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64((a), 32), 1), 1), 1)) 396 | 397 | // Left rotate by 36: Rotate left by 32, then left by 4. 398 | #define leftRotate36_64(a) (leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64((a), 32), 1), 1), 1), 1)) 399 | 400 | // Left rotate by 37: Rotate left by 40, then right by 3. 401 | #define leftRotate37_64(a) (rightRotate_64(rightRotate_64(rightRotate_64(leftRotate_64((a), 40), 1), 1), 1)) 402 | 403 | // Left rotate by 38: Rotate left by 40, then right by 2. 404 | #define leftRotate38_64(a) (rightRotate_64(rightRotate_64(leftRotate_64((a), 40), 1), 1)) 405 | 406 | // Left rotate by 39: Rotate left by 40, then right by 1. 407 | #define leftRotate39_64(a) (rightRotate_64(leftRotate_64((a), 40), 1)) 408 | 409 | // Left rotate by 40. 410 | #define leftRotate40_64(a) (leftRotate_64((a), 40)) 411 | 412 | // Left rotate by 41: Rotate left by 40, then left by 1. 413 | #define leftRotate41_64(a) (leftRotate_64(leftRotate_64((a), 40), 1)) 414 | 415 | // Left rotate by 42: Rotate left by 40, then left by 2. 416 | #define leftRotate42_64(a) (leftRotate_64(leftRotate_64(leftRotate_64((a), 40), 1), 1)) 417 | 418 | // Left rotate by 43: Rotate left by 40, then left by 3. 419 | #define leftRotate43_64(a) (leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64((a), 40), 1), 1), 1)) 420 | 421 | // Left rotate by 44: Rotate left by 40, then left by 4. 422 | #define leftRotate44_64(a) (leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64((a), 40), 1), 1), 1), 1)) 423 | 424 | // Left rotate by 45: Rotate left by 48, then right by 3. 425 | #define leftRotate45_64(a) (rightRotate_64(rightRotate_64(rightRotate_64(leftRotate_64((a), 48), 1), 1), 1)) 426 | 427 | // Left rotate by 46: Rotate left by 48, then right by 2. 428 | #define leftRotate46_64(a) (rightRotate_64(rightRotate_64(leftRotate_64((a), 48), 1), 1)) 429 | 430 | // Left rotate by 47: Rotate left by 48, then right by 1. 431 | #define leftRotate47_64(a) (rightRotate_64(leftRotate_64((a), 48), 1)) 432 | 433 | // Left rotate by 48. 434 | #define leftRotate48_64(a) (leftRotate_64((a), 48)) 435 | 436 | // Left rotate by 49: Rotate left by 48, then left by 1. 437 | #define leftRotate49_64(a) (leftRotate_64(leftRotate_64((a), 48), 1)) 438 | 439 | // Left rotate by 50: Rotate left by 48, then left by 2. 440 | #define leftRotate50_64(a) (leftRotate_64(leftRotate_64(leftRotate_64((a), 48), 1), 1)) 441 | 442 | // Left rotate by 51: Rotate left by 48, then left by 3. 443 | #define leftRotate51_64(a) (leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64((a), 48), 1), 1), 1)) 444 | 445 | // Left rotate by 52: Rotate left by 48, then left by 4. 446 | #define leftRotate52_64(a) (leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64((a), 48), 1), 1), 1), 1)) 447 | 448 | // Left rotate by 53: Rotate left by 56, then right by 3. 449 | #define leftRotate53_64(a) (rightRotate_64(rightRotate_64(rightRotate_64(leftRotate_64((a), 56), 1), 1), 1)) 450 | 451 | // Left rotate by 54: Rotate left by 56, then right by 2. 452 | #define leftRotate54_64(a) (rightRotate_64(rightRotate_64(leftRotate_64((a), 56), 1), 1)) 453 | 454 | // Left rotate by 55: Rotate left by 56, then right by 1. 455 | #define leftRotate55_64(a) (rightRotate_64(leftRotate_64((a), 56), 1)) 456 | 457 | // Left rotate by 56. 458 | #define leftRotate56_64(a) (leftRotate_64((a), 56)) 459 | 460 | // Left rotate by 57: Rotate left by 56, then left by 1. 461 | #define leftRotate57_64(a) (leftRotate_64(leftRotate_64((a), 56), 1)) 462 | 463 | // Left rotate by 58: Rotate left by 56, then left by 2. 464 | #define leftRotate58_64(a) (leftRotate_64(leftRotate_64(leftRotate_64((a), 56), 1), 1)) 465 | 466 | // Left rotate by 59: Rotate left by 56, then left by 3. 467 | #define leftRotate59_64(a) (leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64((a), 56), 1), 1), 1)) 468 | 469 | // Left rotate by 60: Rotate left by 60, then left by 4. 470 | #define leftRotate60_64(a) (leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64((a), 56), 1), 1), 1), 1)) 471 | 472 | // Left rotate by 61: Rotate right by 3. 473 | #define leftRotate61_64(a) (rightRotate_64(rightRotate_64(rightRotate_64((a), 1), 1), 1)) 474 | 475 | // Left rotate by 62: Rotate right by 2. 476 | #define leftRotate62_64(a) (rightRotate_64(rightRotate_64((a), 1), 1)) 477 | 478 | // Left rotate by 63: Rotate right by 1. 479 | #define leftRotate63_64(a) (rightRotate_64((a), 1)) 480 | 481 | // Define the 64-bit right rotations in terms of left rotations. 482 | #define rightRotate1_64(a) (leftRotate63_64((a))) 483 | #define rightRotate2_64(a) (leftRotate62_64((a))) 484 | #define rightRotate3_64(a) (leftRotate61_64((a))) 485 | #define rightRotate4_64(a) (leftRotate60_64((a))) 486 | #define rightRotate5_64(a) (leftRotate59_64((a))) 487 | #define rightRotate6_64(a) (leftRotate58_64((a))) 488 | #define rightRotate7_64(a) (leftRotate57_64((a))) 489 | #define rightRotate8_64(a) (leftRotate56_64((a))) 490 | #define rightRotate9_64(a) (leftRotate55_64((a))) 491 | #define rightRotate10_64(a) (leftRotate54_64((a))) 492 | #define rightRotate11_64(a) (leftRotate53_64((a))) 493 | #define rightRotate12_64(a) (leftRotate52_64((a))) 494 | #define rightRotate13_64(a) (leftRotate51_64((a))) 495 | #define rightRotate14_64(a) (leftRotate50_64((a))) 496 | #define rightRotate15_64(a) (leftRotate49_64((a))) 497 | #define rightRotate16_64(a) (leftRotate48_64((a))) 498 | #define rightRotate17_64(a) (leftRotate47_64((a))) 499 | #define rightRotate18_64(a) (leftRotate46_64((a))) 500 | #define rightRotate19_64(a) (leftRotate45_64((a))) 501 | #define rightRotate20_64(a) (leftRotate44_64((a))) 502 | #define rightRotate21_64(a) (leftRotate43_64((a))) 503 | #define rightRotate22_64(a) (leftRotate42_64((a))) 504 | #define rightRotate23_64(a) (leftRotate41_64((a))) 505 | #define rightRotate24_64(a) (leftRotate40_64((a))) 506 | #define rightRotate25_64(a) (leftRotate39_64((a))) 507 | #define rightRotate26_64(a) (leftRotate38_64((a))) 508 | #define rightRotate27_64(a) (leftRotate37_64((a))) 509 | #define rightRotate28_64(a) (leftRotate36_64((a))) 510 | #define rightRotate29_64(a) (leftRotate35_64((a))) 511 | #define rightRotate30_64(a) (leftRotate34_64((a))) 512 | #define rightRotate31_64(a) (leftRotate33_64((a))) 513 | #define rightRotate32_64(a) (leftRotate32_64((a))) 514 | #define rightRotate33_64(a) (leftRotate31_64((a))) 515 | #define rightRotate34_64(a) (leftRotate30_64((a))) 516 | #define rightRotate35_64(a) (leftRotate29_64((a))) 517 | #define rightRotate36_64(a) (leftRotate28_64((a))) 518 | #define rightRotate37_64(a) (leftRotate27_64((a))) 519 | #define rightRotate38_64(a) (leftRotate26_64((a))) 520 | #define rightRotate39_64(a) (leftRotate25_64((a))) 521 | #define rightRotate40_64(a) (leftRotate24_64((a))) 522 | #define rightRotate41_64(a) (leftRotate23_64((a))) 523 | #define rightRotate42_64(a) (leftRotate22_64((a))) 524 | #define rightRotate43_64(a) (leftRotate21_64((a))) 525 | #define rightRotate44_64(a) (leftRotate20_64((a))) 526 | #define rightRotate45_64(a) (leftRotate19_64((a))) 527 | #define rightRotate46_64(a) (leftRotate18_64((a))) 528 | #define rightRotate47_64(a) (leftRotate17_64((a))) 529 | #define rightRotate48_64(a) (leftRotate16_64((a))) 530 | #define rightRotate49_64(a) (leftRotate15_64((a))) 531 | #define rightRotate50_64(a) (leftRotate14_64((a))) 532 | #define rightRotate51_64(a) (leftRotate13_64((a))) 533 | #define rightRotate52_64(a) (leftRotate12_64((a))) 534 | #define rightRotate53_64(a) (leftRotate11_64((a))) 535 | #define rightRotate54_64(a) (leftRotate10_64((a))) 536 | #define rightRotate55_64(a) (leftRotate9_64((a))) 537 | #define rightRotate56_64(a) (leftRotate8_64((a))) 538 | #define rightRotate57_64(a) (leftRotate7_64((a))) 539 | #define rightRotate58_64(a) (leftRotate6_64((a))) 540 | #define rightRotate59_64(a) (leftRotate5_64((a))) 541 | #define rightRotate60_64(a) (leftRotate4_64((a))) 542 | #define rightRotate61_64(a) (leftRotate3_64((a))) 543 | #define rightRotate62_64(a) (leftRotate2_64((a))) 544 | #define rightRotate63_64(a) (leftRotate1_64((a))) 545 | 546 | #else // !CRYPTO_ROTATE64_COMPOSED 547 | 548 | // Rotation macros for 64-bit arguments. 549 | 550 | // Generic left rotate. 551 | #define leftRotate_64(a, bits) \ 552 | (__extension__ ({ \ 553 | uint64_t _temp = (a); \ 554 | (_temp << (bits)) | (_temp >> (64 - (bits))); \ 555 | })) 556 | 557 | // Generic right rotate. 558 | #define rightRotate_64(a, bits) \ 559 | (__extension__ ({ \ 560 | uint64_t _temp = (a); \ 561 | (_temp >> (bits)) | (_temp << (64 - (bits))); \ 562 | })) 563 | 564 | // Left rotate by a specific number of bits. 565 | #define leftRotate1_64(a) (leftRotate_64((a), 1)) 566 | #define leftRotate2_64(a) (leftRotate_64((a), 2)) 567 | #define leftRotate3_64(a) (leftRotate_64((a), 3)) 568 | #define leftRotate4_64(a) (leftRotate_64((a), 4)) 569 | #define leftRotate5_64(a) (leftRotate_64((a), 5)) 570 | #define leftRotate6_64(a) (leftRotate_64((a), 6)) 571 | #define leftRotate7_64(a) (leftRotate_64((a), 7)) 572 | #define leftRotate8_64(a) (leftRotate_64((a), 8)) 573 | #define leftRotate9_64(a) (leftRotate_64((a), 9)) 574 | #define leftRotate10_64(a) (leftRotate_64((a), 10)) 575 | #define leftRotate11_64(a) (leftRotate_64((a), 11)) 576 | #define leftRotate12_64(a) (leftRotate_64((a), 12)) 577 | #define leftRotate13_64(a) (leftRotate_64((a), 13)) 578 | #define leftRotate14_64(a) (leftRotate_64((a), 14)) 579 | #define leftRotate15_64(a) (leftRotate_64((a), 15)) 580 | #define leftRotate16_64(a) (leftRotate_64((a), 16)) 581 | #define leftRotate17_64(a) (leftRotate_64((a), 17)) 582 | #define leftRotate18_64(a) (leftRotate_64((a), 18)) 583 | #define leftRotate19_64(a) (leftRotate_64((a), 19)) 584 | #define leftRotate20_64(a) (leftRotate_64((a), 20)) 585 | #define leftRotate21_64(a) (leftRotate_64((a), 21)) 586 | #define leftRotate22_64(a) (leftRotate_64((a), 22)) 587 | #define leftRotate23_64(a) (leftRotate_64((a), 23)) 588 | #define leftRotate24_64(a) (leftRotate_64((a), 24)) 589 | #define leftRotate25_64(a) (leftRotate_64((a), 25)) 590 | #define leftRotate26_64(a) (leftRotate_64((a), 26)) 591 | #define leftRotate27_64(a) (leftRotate_64((a), 27)) 592 | #define leftRotate28_64(a) (leftRotate_64((a), 28)) 593 | #define leftRotate29_64(a) (leftRotate_64((a), 29)) 594 | #define leftRotate30_64(a) (leftRotate_64((a), 30)) 595 | #define leftRotate31_64(a) (leftRotate_64((a), 31)) 596 | #define leftRotate32_64(a) (leftRotate_64((a), 32)) 597 | #define leftRotate33_64(a) (leftRotate_64((a), 33)) 598 | #define leftRotate34_64(a) (leftRotate_64((a), 34)) 599 | #define leftRotate35_64(a) (leftRotate_64((a), 35)) 600 | #define leftRotate36_64(a) (leftRotate_64((a), 36)) 601 | #define leftRotate37_64(a) (leftRotate_64((a), 37)) 602 | #define leftRotate38_64(a) (leftRotate_64((a), 38)) 603 | #define leftRotate39_64(a) (leftRotate_64((a), 39)) 604 | #define leftRotate40_64(a) (leftRotate_64((a), 40)) 605 | #define leftRotate41_64(a) (leftRotate_64((a), 41)) 606 | #define leftRotate42_64(a) (leftRotate_64((a), 42)) 607 | #define leftRotate43_64(a) (leftRotate_64((a), 43)) 608 | #define leftRotate44_64(a) (leftRotate_64((a), 44)) 609 | #define leftRotate45_64(a) (leftRotate_64((a), 45)) 610 | #define leftRotate46_64(a) (leftRotate_64((a), 46)) 611 | #define leftRotate47_64(a) (leftRotate_64((a), 47)) 612 | #define leftRotate48_64(a) (leftRotate_64((a), 48)) 613 | #define leftRotate49_64(a) (leftRotate_64((a), 49)) 614 | #define leftRotate50_64(a) (leftRotate_64((a), 50)) 615 | #define leftRotate51_64(a) (leftRotate_64((a), 51)) 616 | #define leftRotate52_64(a) (leftRotate_64((a), 52)) 617 | #define leftRotate53_64(a) (leftRotate_64((a), 53)) 618 | #define leftRotate54_64(a) (leftRotate_64((a), 54)) 619 | #define leftRotate55_64(a) (leftRotate_64((a), 55)) 620 | #define leftRotate56_64(a) (leftRotate_64((a), 56)) 621 | #define leftRotate57_64(a) (leftRotate_64((a), 57)) 622 | #define leftRotate58_64(a) (leftRotate_64((a), 58)) 623 | #define leftRotate59_64(a) (leftRotate_64((a), 59)) 624 | #define leftRotate60_64(a) (leftRotate_64((a), 60)) 625 | #define leftRotate61_64(a) (leftRotate_64((a), 61)) 626 | #define leftRotate62_64(a) (leftRotate_64((a), 62)) 627 | #define leftRotate63_64(a) (leftRotate_64((a), 63)) 628 | 629 | // Right rotate by a specific number of bits. 630 | #define rightRotate1_64(a) (rightRotate_64((a), 1)) 631 | #define rightRotate2_64(a) (rightRotate_64((a), 2)) 632 | #define rightRotate3_64(a) (rightRotate_64((a), 3)) 633 | #define rightRotate4_64(a) (rightRotate_64((a), 4)) 634 | #define rightRotate5_64(a) (rightRotate_64((a), 5)) 635 | #define rightRotate6_64(a) (rightRotate_64((a), 6)) 636 | #define rightRotate7_64(a) (rightRotate_64((a), 7)) 637 | #define rightRotate8_64(a) (rightRotate_64((a), 8)) 638 | #define rightRotate9_64(a) (rightRotate_64((a), 9)) 639 | #define rightRotate10_64(a) (rightRotate_64((a), 10)) 640 | #define rightRotate11_64(a) (rightRotate_64((a), 11)) 641 | #define rightRotate12_64(a) (rightRotate_64((a), 12)) 642 | #define rightRotate13_64(a) (rightRotate_64((a), 13)) 643 | #define rightRotate14_64(a) (rightRotate_64((a), 14)) 644 | #define rightRotate15_64(a) (rightRotate_64((a), 15)) 645 | #define rightRotate16_64(a) (rightRotate_64((a), 16)) 646 | #define rightRotate17_64(a) (rightRotate_64((a), 17)) 647 | #define rightRotate18_64(a) (rightRotate_64((a), 18)) 648 | #define rightRotate19_64(a) (rightRotate_64((a), 19)) 649 | #define rightRotate20_64(a) (rightRotate_64((a), 20)) 650 | #define rightRotate21_64(a) (rightRotate_64((a), 21)) 651 | #define rightRotate22_64(a) (rightRotate_64((a), 22)) 652 | #define rightRotate23_64(a) (rightRotate_64((a), 23)) 653 | #define rightRotate24_64(a) (rightRotate_64((a), 24)) 654 | #define rightRotate25_64(a) (rightRotate_64((a), 25)) 655 | #define rightRotate26_64(a) (rightRotate_64((a), 26)) 656 | #define rightRotate27_64(a) (rightRotate_64((a), 27)) 657 | #define rightRotate28_64(a) (rightRotate_64((a), 28)) 658 | #define rightRotate29_64(a) (rightRotate_64((a), 29)) 659 | #define rightRotate30_64(a) (rightRotate_64((a), 30)) 660 | #define rightRotate31_64(a) (rightRotate_64((a), 31)) 661 | #define rightRotate32_64(a) (rightRotate_64((a), 32)) 662 | #define rightRotate33_64(a) (rightRotate_64((a), 33)) 663 | #define rightRotate34_64(a) (rightRotate_64((a), 34)) 664 | #define rightRotate35_64(a) (rightRotate_64((a), 35)) 665 | #define rightRotate36_64(a) (rightRotate_64((a), 36)) 666 | #define rightRotate37_64(a) (rightRotate_64((a), 37)) 667 | #define rightRotate38_64(a) (rightRotate_64((a), 38)) 668 | #define rightRotate39_64(a) (rightRotate_64((a), 39)) 669 | #define rightRotate40_64(a) (rightRotate_64((a), 40)) 670 | #define rightRotate41_64(a) (rightRotate_64((a), 41)) 671 | #define rightRotate42_64(a) (rightRotate_64((a), 42)) 672 | #define rightRotate43_64(a) (rightRotate_64((a), 43)) 673 | #define rightRotate44_64(a) (rightRotate_64((a), 44)) 674 | #define rightRotate45_64(a) (rightRotate_64((a), 45)) 675 | #define rightRotate46_64(a) (rightRotate_64((a), 46)) 676 | #define rightRotate47_64(a) (rightRotate_64((a), 47)) 677 | #define rightRotate48_64(a) (rightRotate_64((a), 48)) 678 | #define rightRotate49_64(a) (rightRotate_64((a), 49)) 679 | #define rightRotate50_64(a) (rightRotate_64((a), 50)) 680 | #define rightRotate51_64(a) (rightRotate_64((a), 51)) 681 | #define rightRotate52_64(a) (rightRotate_64((a), 52)) 682 | #define rightRotate53_64(a) (rightRotate_64((a), 53)) 683 | #define rightRotate54_64(a) (rightRotate_64((a), 54)) 684 | #define rightRotate55_64(a) (rightRotate_64((a), 55)) 685 | #define rightRotate56_64(a) (rightRotate_64((a), 56)) 686 | #define rightRotate57_64(a) (rightRotate_64((a), 57)) 687 | #define rightRotate58_64(a) (rightRotate_64((a), 58)) 688 | #define rightRotate59_64(a) (rightRotate_64((a), 59)) 689 | #define rightRotate60_64(a) (rightRotate_64((a), 60)) 690 | #define rightRotate61_64(a) (rightRotate_64((a), 61)) 691 | #define rightRotate62_64(a) (rightRotate_64((a), 62)) 692 | #define rightRotate63_64(a) (rightRotate_64((a), 63)) 693 | 694 | #endif // !CRYPTO_ROTATE64_COMPOSED 695 | 696 | #endif 697 | -------------------------------------------------------------------------------- /src/libraries/minilzo/lzoconf.h: -------------------------------------------------------------------------------- 1 | /* lzoconf.h -- configuration of the LZO data compression library 2 | 3 | This file is part of the LZO real-time data compression library. 4 | 5 | Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer 6 | All Rights Reserved. 7 | 8 | The LZO library is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU General Public License as 10 | published by the Free Software Foundation; either version 2 of 11 | the License, or (at your option) any later version. 12 | 13 | The LZO library is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with the LZO library; see the file COPYING. 20 | If not, write to the Free Software Foundation, Inc., 21 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 22 | 23 | Markus F.X.J. Oberhumer 24 | 25 | http://www.oberhumer.com/opensource/lzo/ 26 | */ 27 | 28 | 29 | #ifndef __LZOCONF_H_INCLUDED 30 | #define __LZOCONF_H_INCLUDED 1 31 | 32 | #define LZO_VERSION 0x20a0 /* 2.10 */ 33 | #define LZO_VERSION_STRING "2.10" 34 | #define LZO_VERSION_DATE "Mar 01 2017" 35 | 36 | /* internal Autoconf configuration file - only used when building LZO */ 37 | #if defined(LZO_HAVE_CONFIG_H) 38 | # include 39 | #endif 40 | #include 41 | #include 42 | 43 | 44 | /*********************************************************************** 45 | // LZO requires a conforming 46 | ************************************************************************/ 47 | 48 | #if !defined(CHAR_BIT) || (CHAR_BIT != 8) 49 | # error "invalid CHAR_BIT" 50 | #endif 51 | #if !defined(UCHAR_MAX) || !defined(USHRT_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX) 52 | # error "check your compiler installation" 53 | #endif 54 | #if (USHRT_MAX < 1) || (UINT_MAX < 1) || (ULONG_MAX < 1) 55 | # error "your limits.h macros are broken" 56 | #endif 57 | 58 | /* get OS and architecture defines */ 59 | #ifndef __LZODEFS_H_INCLUDED 60 | #include 61 | #endif 62 | 63 | 64 | #ifdef __cplusplus 65 | extern "C" { 66 | #endif 67 | 68 | 69 | /*********************************************************************** 70 | // some core defines 71 | ************************************************************************/ 72 | 73 | /* memory checkers */ 74 | #if !defined(__LZO_CHECKER) 75 | # if defined(__BOUNDS_CHECKING_ON) 76 | # define __LZO_CHECKER 1 77 | # elif defined(__CHECKER__) 78 | # define __LZO_CHECKER 1 79 | # elif defined(__INSURE__) 80 | # define __LZO_CHECKER 1 81 | # elif defined(__PURIFY__) 82 | # define __LZO_CHECKER 1 83 | # endif 84 | #endif 85 | 86 | 87 | /*********************************************************************** 88 | // integral and pointer types 89 | ************************************************************************/ 90 | 91 | /* lzo_uint must match size_t */ 92 | #if !defined(LZO_UINT_MAX) 93 | # if (LZO_ABI_LLP64) 94 | # if (LZO_OS_WIN64) 95 | typedef unsigned __int64 lzo_uint; 96 | typedef __int64 lzo_int; 97 | # define LZO_TYPEOF_LZO_INT LZO_TYPEOF___INT64 98 | # else 99 | typedef lzo_ullong_t lzo_uint; 100 | typedef lzo_llong_t lzo_int; 101 | # define LZO_TYPEOF_LZO_INT LZO_TYPEOF_LONG_LONG 102 | # endif 103 | # define LZO_SIZEOF_LZO_INT 8 104 | # define LZO_UINT_MAX 0xffffffffffffffffull 105 | # define LZO_INT_MAX 9223372036854775807LL 106 | # define LZO_INT_MIN (-1LL - LZO_INT_MAX) 107 | # elif (LZO_ABI_IP32L64) /* MIPS R5900 */ 108 | typedef unsigned int lzo_uint; 109 | typedef int lzo_int; 110 | # define LZO_SIZEOF_LZO_INT LZO_SIZEOF_INT 111 | # define LZO_TYPEOF_LZO_INT LZO_TYPEOF_INT 112 | # define LZO_UINT_MAX UINT_MAX 113 | # define LZO_INT_MAX INT_MAX 114 | # define LZO_INT_MIN INT_MIN 115 | # elif (ULONG_MAX >= LZO_0xffffffffL) 116 | typedef unsigned long lzo_uint; 117 | typedef long lzo_int; 118 | # define LZO_SIZEOF_LZO_INT LZO_SIZEOF_LONG 119 | # define LZO_TYPEOF_LZO_INT LZO_TYPEOF_LONG 120 | # define LZO_UINT_MAX ULONG_MAX 121 | # define LZO_INT_MAX LONG_MAX 122 | # define LZO_INT_MIN LONG_MIN 123 | # else 124 | # error "lzo_uint" 125 | # endif 126 | #endif 127 | 128 | /* The larger type of lzo_uint and lzo_uint32_t. */ 129 | #if (LZO_SIZEOF_LZO_INT >= 4) 130 | # define lzo_xint lzo_uint 131 | #else 132 | # define lzo_xint lzo_uint32_t 133 | #endif 134 | 135 | typedef int lzo_bool; 136 | 137 | /* sanity checks */ 138 | LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int) == LZO_SIZEOF_LZO_INT) 139 | LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == LZO_SIZEOF_LZO_INT) 140 | LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_xint) >= sizeof(lzo_uint)) 141 | LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_xint) >= sizeof(lzo_uint32_t)) 142 | 143 | #ifndef __LZO_MMODEL 144 | #define __LZO_MMODEL /*empty*/ 145 | #endif 146 | 147 | /* no typedef here because of const-pointer issues */ 148 | #define lzo_bytep unsigned char __LZO_MMODEL * 149 | #define lzo_charp char __LZO_MMODEL * 150 | #define lzo_voidp void __LZO_MMODEL * 151 | #define lzo_shortp short __LZO_MMODEL * 152 | #define lzo_ushortp unsigned short __LZO_MMODEL * 153 | #define lzo_intp lzo_int __LZO_MMODEL * 154 | #define lzo_uintp lzo_uint __LZO_MMODEL * 155 | #define lzo_xintp lzo_xint __LZO_MMODEL * 156 | #define lzo_voidpp lzo_voidp __LZO_MMODEL * 157 | #define lzo_bytepp lzo_bytep __LZO_MMODEL * 158 | 159 | #define lzo_int8_tp lzo_int8_t __LZO_MMODEL * 160 | #define lzo_uint8_tp lzo_uint8_t __LZO_MMODEL * 161 | #define lzo_int16_tp lzo_int16_t __LZO_MMODEL * 162 | #define lzo_uint16_tp lzo_uint16_t __LZO_MMODEL * 163 | #define lzo_int32_tp lzo_int32_t __LZO_MMODEL * 164 | #define lzo_uint32_tp lzo_uint32_t __LZO_MMODEL * 165 | #if defined(lzo_int64_t) 166 | #define lzo_int64_tp lzo_int64_t __LZO_MMODEL * 167 | #define lzo_uint64_tp lzo_uint64_t __LZO_MMODEL * 168 | #endif 169 | 170 | /* Older LZO versions used to support ancient systems and memory models 171 | * such as 16-bit MSDOS with __huge pointers or Cray PVP, but these 172 | * obsolete configurations are not supported any longer. 173 | */ 174 | #if defined(__LZO_MMODEL_HUGE) 175 | #error "__LZO_MMODEL_HUGE memory model is unsupported" 176 | #endif 177 | #if (LZO_MM_PVP) 178 | #error "LZO_MM_PVP memory model is unsupported" 179 | #endif 180 | #if (LZO_SIZEOF_INT < 4) 181 | #error "LZO_SIZEOF_INT < 4 is unsupported" 182 | #endif 183 | #if (__LZO_UINTPTR_T_IS_POINTER) 184 | #error "__LZO_UINTPTR_T_IS_POINTER is unsupported" 185 | #endif 186 | LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) >= 4) 187 | LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) >= 4) 188 | /* Strange configurations where sizeof(lzo_uint) != sizeof(size_t) should 189 | * work but have not received much testing lately, so be strict here. 190 | */ 191 | LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == sizeof(size_t)) 192 | LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == sizeof(ptrdiff_t)) 193 | LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == sizeof(lzo_uintptr_t)) 194 | LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(void *) == sizeof(lzo_uintptr_t)) 195 | LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(char *) == sizeof(lzo_uintptr_t)) 196 | LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long *) == sizeof(lzo_uintptr_t)) 197 | LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(void *) == sizeof(lzo_voidp)) 198 | LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(char *) == sizeof(lzo_bytep)) 199 | 200 | 201 | /*********************************************************************** 202 | // function types 203 | ************************************************************************/ 204 | 205 | /* name mangling */ 206 | #if !defined(__LZO_EXTERN_C) 207 | # ifdef __cplusplus 208 | # define __LZO_EXTERN_C extern "C" 209 | # else 210 | # define __LZO_EXTERN_C extern 211 | # endif 212 | #endif 213 | 214 | /* calling convention */ 215 | #if !defined(__LZO_CDECL) 216 | # define __LZO_CDECL __lzo_cdecl 217 | #endif 218 | 219 | /* DLL export information */ 220 | #if !defined(__LZO_EXPORT1) 221 | # define __LZO_EXPORT1 /*empty*/ 222 | #endif 223 | #if !defined(__LZO_EXPORT2) 224 | # define __LZO_EXPORT2 /*empty*/ 225 | #endif 226 | 227 | /* __cdecl calling convention for public C and assembly functions */ 228 | #if !defined(LZO_PUBLIC) 229 | # define LZO_PUBLIC(r) __LZO_EXPORT1 r __LZO_EXPORT2 __LZO_CDECL 230 | #endif 231 | #if !defined(LZO_EXTERN) 232 | # define LZO_EXTERN(r) __LZO_EXTERN_C LZO_PUBLIC(r) 233 | #endif 234 | #if !defined(LZO_PRIVATE) 235 | # define LZO_PRIVATE(r) static r __LZO_CDECL 236 | #endif 237 | 238 | /* function types */ 239 | typedef int 240 | (__LZO_CDECL *lzo_compress_t) ( const lzo_bytep src, lzo_uint src_len, 241 | lzo_bytep dst, lzo_uintp dst_len, 242 | lzo_voidp wrkmem ); 243 | 244 | typedef int 245 | (__LZO_CDECL *lzo_decompress_t) ( const lzo_bytep src, lzo_uint src_len, 246 | lzo_bytep dst, lzo_uintp dst_len, 247 | lzo_voidp wrkmem ); 248 | 249 | typedef int 250 | (__LZO_CDECL *lzo_optimize_t) ( lzo_bytep src, lzo_uint src_len, 251 | lzo_bytep dst, lzo_uintp dst_len, 252 | lzo_voidp wrkmem ); 253 | 254 | typedef int 255 | (__LZO_CDECL *lzo_compress_dict_t)(const lzo_bytep src, lzo_uint src_len, 256 | lzo_bytep dst, lzo_uintp dst_len, 257 | lzo_voidp wrkmem, 258 | const lzo_bytep dict, lzo_uint dict_len ); 259 | 260 | typedef int 261 | (__LZO_CDECL *lzo_decompress_dict_t)(const lzo_bytep src, lzo_uint src_len, 262 | lzo_bytep dst, lzo_uintp dst_len, 263 | lzo_voidp wrkmem, 264 | const lzo_bytep dict, lzo_uint dict_len ); 265 | 266 | 267 | /* Callback interface. Currently only the progress indicator ("nprogress") 268 | * is used, but this may change in a future release. */ 269 | 270 | struct lzo_callback_t; 271 | typedef struct lzo_callback_t lzo_callback_t; 272 | #define lzo_callback_p lzo_callback_t __LZO_MMODEL * 273 | 274 | /* malloc & free function types */ 275 | typedef lzo_voidp (__LZO_CDECL *lzo_alloc_func_t) 276 | (lzo_callback_p self, lzo_uint items, lzo_uint size); 277 | typedef void (__LZO_CDECL *lzo_free_func_t) 278 | (lzo_callback_p self, lzo_voidp ptr); 279 | 280 | /* a progress indicator callback function */ 281 | typedef void (__LZO_CDECL *lzo_progress_func_t) 282 | (lzo_callback_p, lzo_uint, lzo_uint, int); 283 | 284 | struct lzo_callback_t 285 | { 286 | /* custom allocators (set to 0 to disable) */ 287 | lzo_alloc_func_t nalloc; /* [not used right now] */ 288 | lzo_free_func_t nfree; /* [not used right now] */ 289 | 290 | /* a progress indicator callback function (set to 0 to disable) */ 291 | lzo_progress_func_t nprogress; 292 | 293 | /* INFO: the first parameter "self" of the nalloc/nfree/nprogress 294 | * callbacks points back to this struct, so you are free to store 295 | * some extra info in the following variables. */ 296 | lzo_voidp user1; 297 | lzo_xint user2; 298 | lzo_xint user3; 299 | }; 300 | 301 | 302 | /*********************************************************************** 303 | // error codes and prototypes 304 | ************************************************************************/ 305 | 306 | /* Error codes for the compression/decompression functions. Negative 307 | * values are errors, positive values will be used for special but 308 | * normal events. 309 | */ 310 | #define LZO_E_OK 0 311 | #define LZO_E_ERROR (-1) 312 | #define LZO_E_OUT_OF_MEMORY (-2) /* [lzo_alloc_func_t failure] */ 313 | #define LZO_E_NOT_COMPRESSIBLE (-3) /* [not used right now] */ 314 | #define LZO_E_INPUT_OVERRUN (-4) 315 | #define LZO_E_OUTPUT_OVERRUN (-5) 316 | #define LZO_E_LOOKBEHIND_OVERRUN (-6) 317 | #define LZO_E_EOF_NOT_FOUND (-7) 318 | #define LZO_E_INPUT_NOT_CONSUMED (-8) 319 | #define LZO_E_NOT_YET_IMPLEMENTED (-9) /* [not used right now] */ 320 | #define LZO_E_INVALID_ARGUMENT (-10) 321 | #define LZO_E_INVALID_ALIGNMENT (-11) /* pointer argument is not properly aligned */ 322 | #define LZO_E_OUTPUT_NOT_CONSUMED (-12) 323 | #define LZO_E_INTERNAL_ERROR (-99) 324 | 325 | 326 | #ifndef lzo_sizeof_dict_t 327 | # define lzo_sizeof_dict_t ((unsigned)sizeof(lzo_bytep)) 328 | #endif 329 | 330 | /* lzo_init() should be the first function you call. 331 | * Check the return code ! 332 | * 333 | * lzo_init() is a macro to allow checking that the library and the 334 | * compiler's view of various types are consistent. 335 | */ 336 | #define lzo_init() __lzo_init_v2(LZO_VERSION,(int)sizeof(short),(int)sizeof(int),\ 337 | (int)sizeof(long),(int)sizeof(lzo_uint32_t),(int)sizeof(lzo_uint),\ 338 | (int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\ 339 | (int)sizeof(lzo_callback_t)) 340 | LZO_EXTERN(int) __lzo_init_v2(unsigned,int,int,int,int,int,int,int,int,int); 341 | 342 | /* version functions (useful for shared libraries) */ 343 | LZO_EXTERN(unsigned) lzo_version(void); 344 | LZO_EXTERN(const char *) lzo_version_string(void); 345 | LZO_EXTERN(const char *) lzo_version_date(void); 346 | LZO_EXTERN(const lzo_charp) _lzo_version_string(void); 347 | LZO_EXTERN(const lzo_charp) _lzo_version_date(void); 348 | 349 | /* string functions */ 350 | LZO_EXTERN(int) 351 | lzo_memcmp(const lzo_voidp a, const lzo_voidp b, lzo_uint len); 352 | LZO_EXTERN(lzo_voidp) 353 | lzo_memcpy(lzo_voidp dst, const lzo_voidp src, lzo_uint len); 354 | LZO_EXTERN(lzo_voidp) 355 | lzo_memmove(lzo_voidp dst, const lzo_voidp src, lzo_uint len); 356 | LZO_EXTERN(lzo_voidp) 357 | lzo_memset(lzo_voidp buf, int c, lzo_uint len); 358 | 359 | /* checksum functions */ 360 | LZO_EXTERN(lzo_uint32_t) 361 | lzo_adler32(lzo_uint32_t c, const lzo_bytep buf, lzo_uint len); 362 | LZO_EXTERN(lzo_uint32_t) 363 | lzo_crc32(lzo_uint32_t c, const lzo_bytep buf, lzo_uint len); 364 | LZO_EXTERN(const lzo_uint32_tp) 365 | lzo_get_crc32_table(void); 366 | 367 | /* misc. */ 368 | LZO_EXTERN(int) _lzo_config_check(void); 369 | typedef union { 370 | lzo_voidp a00; lzo_bytep a01; lzo_uint a02; lzo_xint a03; lzo_uintptr_t a04; 371 | void *a05; unsigned char *a06; unsigned long a07; size_t a08; ptrdiff_t a09; 372 | #if defined(lzo_int64_t) 373 | lzo_uint64_t a10; 374 | #endif 375 | } lzo_align_t; 376 | 377 | /* align a char pointer on a boundary that is a multiple of 'size' */ 378 | LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp p, lzo_uint size); 379 | #define LZO_PTR_ALIGN_UP(p,size) \ 380 | ((p) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(p),(lzo_uint)(size))) 381 | 382 | 383 | /*********************************************************************** 384 | // deprecated macros - only for backward compatibility 385 | ************************************************************************/ 386 | 387 | /* deprecated - use 'lzo_bytep' instead of 'lzo_byte *' */ 388 | #define lzo_byte unsigned char 389 | /* deprecated type names */ 390 | #define lzo_int32 lzo_int32_t 391 | #define lzo_uint32 lzo_uint32_t 392 | #define lzo_int32p lzo_int32_t __LZO_MMODEL * 393 | #define lzo_uint32p lzo_uint32_t __LZO_MMODEL * 394 | #define LZO_INT32_MAX LZO_INT32_C(2147483647) 395 | #define LZO_UINT32_MAX LZO_UINT32_C(4294967295) 396 | #if defined(lzo_int64_t) 397 | #define lzo_int64 lzo_int64_t 398 | #define lzo_uint64 lzo_uint64_t 399 | #define lzo_int64p lzo_int64_t __LZO_MMODEL * 400 | #define lzo_uint64p lzo_uint64_t __LZO_MMODEL * 401 | #define LZO_INT64_MAX LZO_INT64_C(9223372036854775807) 402 | #define LZO_UINT64_MAX LZO_UINT64_C(18446744073709551615) 403 | #endif 404 | /* deprecated types */ 405 | typedef union { lzo_bytep a; lzo_uint b; } __lzo_pu_u; 406 | typedef union { lzo_bytep a; lzo_uint32_t b; } __lzo_pu32_u; 407 | /* deprecated defines */ 408 | #if !defined(LZO_SIZEOF_LZO_UINT) 409 | # define LZO_SIZEOF_LZO_UINT LZO_SIZEOF_LZO_INT 410 | #endif 411 | 412 | #if defined(LZO_CFG_COMPAT) 413 | 414 | #define __LZOCONF_H 1 415 | 416 | #if defined(LZO_ARCH_I086) 417 | # define __LZO_i386 1 418 | #elif defined(LZO_ARCH_I386) 419 | # define __LZO_i386 1 420 | #endif 421 | 422 | #if defined(LZO_OS_DOS16) 423 | # define __LZO_DOS 1 424 | # define __LZO_DOS16 1 425 | #elif defined(LZO_OS_DOS32) 426 | # define __LZO_DOS 1 427 | #elif defined(LZO_OS_WIN16) 428 | # define __LZO_WIN 1 429 | # define __LZO_WIN16 1 430 | #elif defined(LZO_OS_WIN32) 431 | # define __LZO_WIN 1 432 | #endif 433 | 434 | #define __LZO_CMODEL /*empty*/ 435 | #define __LZO_DMODEL /*empty*/ 436 | #define __LZO_ENTRY __LZO_CDECL 437 | #define LZO_EXTERN_CDECL LZO_EXTERN 438 | #define LZO_ALIGN LZO_PTR_ALIGN_UP 439 | 440 | #define lzo_compress_asm_t lzo_compress_t 441 | #define lzo_decompress_asm_t lzo_decompress_t 442 | 443 | #endif /* LZO_CFG_COMPAT */ 444 | 445 | 446 | #ifdef __cplusplus 447 | } /* extern "C" */ 448 | #endif 449 | 450 | #endif /* already included */ 451 | 452 | 453 | /* vim:set ts=4 sw=4 et: */ 454 | -------------------------------------------------------------------------------- /src/libraries/minilzo/minilzo.h: -------------------------------------------------------------------------------- 1 | /* minilzo.h -- mini subset of the LZO real-time data compression library 2 | 3 | This file is part of the LZO real-time data compression library. 4 | 5 | Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer 6 | All Rights Reserved. 7 | 8 | The LZO library is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU General Public License as 10 | published by the Free Software Foundation; either version 2 of 11 | the License, or (at your option) any later version. 12 | 13 | The LZO library is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with the LZO library; see the file COPYING. 20 | If not, write to the Free Software Foundation, Inc., 21 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 22 | 23 | Markus F.X.J. Oberhumer 24 | 25 | http://www.oberhumer.com/opensource/lzo/ 26 | */ 27 | 28 | /* 29 | * NOTE: 30 | * the full LZO package can be found at 31 | * http://www.oberhumer.com/opensource/lzo/ 32 | */ 33 | 34 | 35 | #ifndef __MINILZO_H_INCLUDED 36 | #define __MINILZO_H_INCLUDED 1 37 | 38 | #define MINILZO_VERSION 0x20a0 /* 2.10 */ 39 | 40 | #if defined(__LZOCONF_H_INCLUDED) 41 | # error "you cannot use both LZO and miniLZO" 42 | #endif 43 | 44 | /* internal Autoconf configuration file - only used when building miniLZO */ 45 | #ifdef MINILZO_HAVE_CONFIG_H 46 | # include 47 | #endif 48 | #include 49 | #include 50 | 51 | #ifndef __LZODEFS_H_INCLUDED 52 | #include "lzodefs.h" 53 | #endif 54 | #undef LZO_HAVE_CONFIG_H 55 | #include "lzoconf.h" 56 | 57 | #if !defined(LZO_VERSION) || (LZO_VERSION != MINILZO_VERSION) 58 | # error "version mismatch in header files" 59 | #endif 60 | 61 | 62 | #ifdef __cplusplus 63 | extern "C" { 64 | #endif 65 | 66 | 67 | /*********************************************************************** 68 | // 69 | ************************************************************************/ 70 | 71 | /* Memory required for the wrkmem parameter. 72 | * When the required size is 0, you can also pass a NULL pointer. 73 | */ 74 | 75 | #define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS 76 | #define LZO1X_1_MEM_COMPRESS ((lzo_uint32_t) (2048L * lzo_sizeof_dict_t)) // origin: 16384L 77 | #define LZO1X_MEM_DECOMPRESS (0) 78 | 79 | 80 | /* compression */ 81 | LZO_EXTERN(int) 82 | lzo1x_1_compress ( const lzo_bytep src, lzo_uint src_len, 83 | lzo_bytep dst, lzo_uintp dst_len, 84 | lzo_voidp wrkmem ); 85 | 86 | /* decompression */ 87 | LZO_EXTERN(int) 88 | lzo1x_decompress ( const lzo_bytep src, lzo_uint src_len, 89 | lzo_bytep dst, lzo_uintp dst_len, 90 | lzo_voidp wrkmem /* NOT USED */ ); 91 | 92 | /* safe decompression with overrun testing */ 93 | LZO_EXTERN(int) 94 | lzo1x_decompress_safe ( const lzo_bytep src, lzo_uint src_len, 95 | lzo_bytep dst, lzo_uintp dst_len, 96 | lzo_voidp wrkmem /* NOT USED */ ); 97 | 98 | 99 | #ifdef __cplusplus 100 | } /* extern "C" */ 101 | #endif 102 | 103 | #endif /* already included */ 104 | 105 | 106 | /* vim:set ts=4 sw=4 et: */ 107 | --------------------------------------------------------------------------------