Add libsodium, cbor and jsmn components
This commit is contained in:
parent
4acb852557
commit
2c5242ca55
|
@ -0,0 +1 @@
|
|||
*/dist/**
|
|
@ -0,0 +1,6 @@
|
|||
[submodule "libsodium/libsodium"]
|
||||
path = libsodium/libsodium
|
||||
url = https://github.com/jedisct1/libsodium.git
|
||||
[submodule "cbor/tinycbor"]
|
||||
path = cbor/tinycbor
|
||||
url = https://github.com/intel/tinycbor.git
|
|
@ -0,0 +1,20 @@
|
|||
idf_component_register(SRCS "tinycbor/src/cborencoder_close_container_checked.c"
|
||||
"tinycbor/src/cborencoder.c"
|
||||
"tinycbor/src/cborerrorstrings.c"
|
||||
"tinycbor/src/cborparser_dup_string.c"
|
||||
"tinycbor/src/cborparser.c"
|
||||
"tinycbor/src/cborpretty_stdio.c"
|
||||
"tinycbor/src/cborpretty.c"
|
||||
"tinycbor/src/cbortojson.c"
|
||||
"tinycbor/src/cborvalidation.c"
|
||||
"tinycbor/src/open_memstream.c"
|
||||
INCLUDE_DIRS "port/include"
|
||||
PRIV_INCLUDE_DIRS "tinycbor/src")
|
||||
|
||||
# for open_memstream.c
|
||||
set_source_files_properties(tinycbor/src/open_memstream.c PROPERTIES COMPILE_DEFINITIONS "__linux__")
|
||||
|
||||
# workaround for the fact that we are passing -ffreestanding to Clang
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-U __STDC_HOSTED__")
|
||||
endif()
|
|
@ -0,0 +1 @@
|
|||
tinycbor/LICENSE
|
|
@ -0,0 +1 @@
|
|||
tinycbor/README
|
|
@ -0,0 +1,5 @@
|
|||
version: "0.5.4"
|
||||
description: "CBOR: Concise Binary Object Representation Library"
|
||||
url: https://github.com/espressif/idf-extra-components/tree/master/cbor
|
||||
dependencies:
|
||||
idf: ">=4.3"
|
|
@ -0,0 +1,2 @@
|
|||
#include "../../tinycbor/src/cbor.h"
|
||||
#include "../../tinycbor/src/cborjson.h"
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 7c349dbb6b8d76db39383b226d3ebdf59b8ab37d
|
|
@ -0,0 +1,10 @@
|
|||
idf_component_register(SRCS "src/jsmn.c"
|
||||
INCLUDE_DIRS "include")
|
||||
|
||||
if(CONFIG_JSMN_PARENT_LINKS)
|
||||
target_compile_definitions(${COMPONENT_LIB} PUBLIC "-DJSMN_PARENT_LINKS")
|
||||
endif()
|
||||
|
||||
if(CONFIG_JSMN_STRICT)
|
||||
target_compile_definitions(${COMPONENT_LIB} PUBLIC "-DJSMN_STRICT")
|
||||
endif()
|
|
@ -0,0 +1,16 @@
|
|||
menu "jsmn"
|
||||
|
||||
|
||||
config JSMN_PARENT_LINKS
|
||||
bool "Enable parent links"
|
||||
default n
|
||||
help
|
||||
You can access to parent node of parsed json
|
||||
|
||||
config JSMN_STRICT
|
||||
bool "Enable strict mode"
|
||||
default n
|
||||
help
|
||||
In strict mode primitives are: numbers and booleans
|
||||
|
||||
endmenu
|
|
@ -0,0 +1,19 @@
|
|||
Copyright (c) 2010 Serge A. Zaitsev
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
|
@ -0,0 +1,168 @@
|
|||
JSMN
|
||||
====
|
||||
|
||||
[![Build Status](https://travis-ci.org/zserge/jsmn.svg?branch=master)](https://travis-ci.org/zserge/jsmn)
|
||||
|
||||
jsmn (pronounced like 'jasmine') is a minimalistic JSON parser in C. It can be
|
||||
easily integrated into resource-limited or embedded projects.
|
||||
|
||||
You can find more information about JSON format at [json.org][1]
|
||||
|
||||
Library sources are available at https://github.com/zserge/jsmn
|
||||
|
||||
The web page with some information about jsmn can be found at
|
||||
[http://zserge.com/jsmn.html][2]
|
||||
|
||||
Philosophy
|
||||
----------
|
||||
|
||||
Most JSON parsers offer you a bunch of functions to load JSON data, parse it
|
||||
and extract any value by its name. jsmn proves that checking the correctness of
|
||||
every JSON packet or allocating temporary objects to store parsed JSON fields
|
||||
often is an overkill.
|
||||
|
||||
JSON format itself is extremely simple, so why should we complicate it?
|
||||
|
||||
jsmn is designed to be **robust** (it should work fine even with erroneous
|
||||
data), **fast** (it should parse data on the fly), **portable** (no superfluous
|
||||
dependencies or non-standard C extensions). And of course, **simplicity** is a
|
||||
key feature - simple code style, simple algorithm, simple integration into
|
||||
other projects.
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
* compatible with C89
|
||||
* no dependencies (even libc!)
|
||||
* highly portable (tested on x86/amd64, ARM, AVR)
|
||||
* about 200 lines of code
|
||||
* extremely small code footprint
|
||||
* API contains only 2 functions
|
||||
* no dynamic memory allocation
|
||||
* incremental single-pass parsing
|
||||
* library code is covered with unit-tests
|
||||
|
||||
Design
|
||||
------
|
||||
|
||||
The rudimentary jsmn object is a **token**. Let's consider a JSON string:
|
||||
|
||||
'{ "name" : "Jack", "age" : 27 }'
|
||||
|
||||
It holds the following tokens:
|
||||
|
||||
* Object: `{ "name" : "Jack", "age" : 27}` (the whole object)
|
||||
* Strings: `"name"`, `"Jack"`, `"age"` (keys and some values)
|
||||
* Number: `27`
|
||||
|
||||
In jsmn, tokens do not hold any data, but point to token boundaries in JSON
|
||||
string instead. In the example above jsmn will create tokens like: Object
|
||||
[0..31], String [3..7], String [12..16], String [20..23], Number [27..29].
|
||||
|
||||
Every jsmn token has a type, which indicates the type of corresponding JSON
|
||||
token. jsmn supports the following token types:
|
||||
|
||||
* Object - a container of key-value pairs, e.g.:
|
||||
`{ "foo":"bar", "x":0.3 }`
|
||||
* Array - a sequence of values, e.g.:
|
||||
`[ 1, 2, 3 ]`
|
||||
* String - a quoted sequence of chars, e.g.: `"foo"`
|
||||
* Primitive - a number, a boolean (`true`, `false`) or `null`
|
||||
|
||||
Besides start/end positions, jsmn tokens for complex types (like arrays
|
||||
or objects) also contain a number of child items, so you can easily follow
|
||||
object hierarchy.
|
||||
|
||||
This approach provides enough information for parsing any JSON data and makes
|
||||
it possible to use zero-copy techniques.
|
||||
|
||||
Install
|
||||
-------
|
||||
|
||||
To clone the repository you should have Git installed. Just run:
|
||||
|
||||
$ git clone https://github.com/zserge/jsmn
|
||||
|
||||
Repository layout is simple: jsmn.c and jsmn.h are library files, tests are in
|
||||
the jsmn\_test.c, you will also find README, LICENSE and Makefile files inside.
|
||||
|
||||
To build the library, run `make`. It is also recommended to run `make test`.
|
||||
Let me know, if some tests fail.
|
||||
|
||||
If build was successful, you should get a `libjsmn.a` library.
|
||||
The header file you should include is called `"jsmn.h"`.
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
Token types are described by `jsmntype_t`:
|
||||
|
||||
typedef enum {
|
||||
JSMN_UNDEFINED = 0,
|
||||
JSMN_OBJECT = 1,
|
||||
JSMN_ARRAY = 2,
|
||||
JSMN_STRING = 3,
|
||||
JSMN_PRIMITIVE = 4
|
||||
} jsmntype_t;
|
||||
|
||||
**Note:** Unlike JSON data types, primitive tokens are not divided into
|
||||
numbers, booleans and null, because one can easily tell the type using the
|
||||
first character:
|
||||
|
||||
* <code>'t', 'f'</code> - boolean
|
||||
* <code>'n'</code> - null
|
||||
* <code>'-', '0'..'9'</code> - number
|
||||
|
||||
Token is an object of `jsmntok_t` type:
|
||||
|
||||
typedef struct {
|
||||
jsmntype_t type; // Token type
|
||||
int start; // Token start position
|
||||
int end; // Token end position
|
||||
int size; // Number of child (nested) tokens
|
||||
} jsmntok_t;
|
||||
|
||||
**Note:** string tokens point to the first character after
|
||||
the opening quote and the previous symbol before final quote. This was made
|
||||
to simplify string extraction from JSON data.
|
||||
|
||||
All job is done by `jsmn_parser` object. You can initialize a new parser using:
|
||||
|
||||
jsmn_parser parser;
|
||||
jsmntok_t tokens[10];
|
||||
|
||||
jsmn_init(&parser);
|
||||
|
||||
// js - pointer to JSON string
|
||||
// tokens - an array of tokens available
|
||||
// 10 - number of tokens available
|
||||
jsmn_parse(&parser, js, strlen(js), tokens, 10);
|
||||
|
||||
This will create a parser, and then it tries to parse up to 10 JSON tokens from
|
||||
the `js` string.
|
||||
|
||||
A non-negative return value of `jsmn_parse` is the number of tokens actually
|
||||
used by the parser.
|
||||
Passing NULL instead of the tokens array would not store parsing results, but
|
||||
instead the function will return the value of tokens needed to parse the given
|
||||
string. This can be useful if you don't know yet how many tokens to allocate.
|
||||
|
||||
If something goes wrong, you will get an error. Error will be one of these:
|
||||
|
||||
* `JSMN_ERROR_INVAL` - bad token, JSON string is corrupted
|
||||
* `JSMN_ERROR_NOMEM` - not enough tokens, JSON string is too large
|
||||
* `JSMN_ERROR_PART` - JSON string is too short, expecting more JSON data
|
||||
|
||||
If you get `JSMN_ERROR_NOMEM`, you can re-allocate more tokens and call
|
||||
`jsmn_parse` once more. If you read json data from the stream, you can
|
||||
periodically call `jsmn_parse` and check if return value is `JSMN_ERROR_PART`.
|
||||
You will get this error until you reach the end of JSON data.
|
||||
|
||||
Other info
|
||||
----------
|
||||
|
||||
This software is distributed under [MIT license](http://www.opensource.org/licenses/mit-license.php),
|
||||
so feel free to integrate it in your commercial products.
|
||||
|
||||
[1]: http://www.json.org/
|
||||
[2]: http://zserge.com/jsmn.html
|
|
@ -0,0 +1,5 @@
|
|||
version: "1.0.0"
|
||||
description: "JSMN: minimalistic JSON parser in C"
|
||||
url: https://github.com/espressif/idf-extra-components/tree/master/jsmn
|
||||
dependencies:
|
||||
idf: ">=4.3"
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright (c) 2010 Serge A. Zaitsev
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file jsmn.h
|
||||
* @brief Definition of the JSMN (Jasmine) JSON parser.
|
||||
*
|
||||
* For more information on JSMN:
|
||||
* @see http://zserge.com/jsmn.html
|
||||
*/
|
||||
|
||||
#ifndef __JSMN_H_
|
||||
#define __JSMN_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* JSON type identifier. Basic types are:
|
||||
* o Object
|
||||
* o Array
|
||||
* o String
|
||||
* o Other primitive: number, boolean (true/false) or null
|
||||
*/
|
||||
typedef enum {
|
||||
JSMN_UNDEFINED = 0,
|
||||
JSMN_OBJECT = 1,
|
||||
JSMN_ARRAY = 2,
|
||||
JSMN_STRING = 3,
|
||||
JSMN_PRIMITIVE = 4
|
||||
} jsmntype_t;
|
||||
|
||||
enum jsmnerr {
|
||||
/* Not enough tokens were provided */
|
||||
JSMN_ERROR_NOMEM = -1,
|
||||
/* Invalid character inside JSON string */
|
||||
JSMN_ERROR_INVAL = -2,
|
||||
/* The string is not a full JSON packet, more bytes expected */
|
||||
JSMN_ERROR_PART = -3
|
||||
};
|
||||
|
||||
/**
|
||||
* JSON token description.
|
||||
* @param type type (object, array, string etc.)
|
||||
* @param start start position in JSON data string
|
||||
* @param end end position in JSON data string
|
||||
*/
|
||||
typedef struct {
|
||||
jsmntype_t type;
|
||||
int start;
|
||||
int end;
|
||||
int size;
|
||||
#ifdef JSMN_PARENT_LINKS
|
||||
int parent;
|
||||
#endif
|
||||
} jsmntok_t;
|
||||
|
||||
/**
|
||||
* JSON parser. Contains an array of token blocks available. Also stores
|
||||
* the string being parsed now and current position in that string
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned int pos; /* offset in the JSON string */
|
||||
unsigned int toknext; /* next token to allocate */
|
||||
int toksuper; /* superior token node, e.g parent object or array */
|
||||
} jsmn_parser;
|
||||
|
||||
/**
|
||||
* Create JSON parser over an array of tokens
|
||||
*/
|
||||
void jsmn_init(jsmn_parser *parser);
|
||||
|
||||
/**
|
||||
* Run JSON parser. It parses a JSON data string into and array of tokens, each describing
|
||||
* a single JSON object.
|
||||
*/
|
||||
int jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
|
||||
jsmntok_t *tokens, unsigned int num_tokens);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __JSMN_H_ */
|
|
@ -0,0 +1,340 @@
|
|||
/*
|
||||
* Copyright (c) 2010 Serge A. Zaitsev
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file jsmn.c
|
||||
* @brief Implementation of the JSMN (Jasmine) JSON parser.
|
||||
*
|
||||
* For more information on JSMN:
|
||||
* @see http://zserge.com/jsmn.html
|
||||
*/
|
||||
|
||||
#include "jsmn.h"
|
||||
|
||||
/**
|
||||
* Allocates a fresh unused token from the token pull.
|
||||
*/
|
||||
static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser,
|
||||
jsmntok_t *tokens, size_t num_tokens) {
|
||||
jsmntok_t *tok;
|
||||
if (parser->toknext >= num_tokens) {
|
||||
return NULL;
|
||||
}
|
||||
tok = &tokens[parser->toknext++];
|
||||
tok->start = tok->end = -1;
|
||||
tok->size = 0;
|
||||
#ifdef JSMN_PARENT_LINKS
|
||||
tok->parent = -1;
|
||||
#endif
|
||||
return tok;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills token type and boundaries.
|
||||
*/
|
||||
static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type,
|
||||
int start, int end) {
|
||||
token->type = type;
|
||||
token->start = start;
|
||||
token->end = end;
|
||||
token->size = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills next available token with JSON primitive.
|
||||
*/
|
||||
static int jsmn_parse_primitive(jsmn_parser *parser, const char *js,
|
||||
size_t len, jsmntok_t *tokens, size_t num_tokens) {
|
||||
jsmntok_t *token;
|
||||
int start;
|
||||
|
||||
start = parser->pos;
|
||||
|
||||
for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
|
||||
switch (js[parser->pos]) {
|
||||
#ifndef JSMN_STRICT
|
||||
/* In strict mode primitive must be followed by "," or "}" or "]" */
|
||||
case ':':
|
||||
#endif
|
||||
case '\t' : case '\r' : case '\n' : case ' ' :
|
||||
case ',' : case ']' : case '}' :
|
||||
goto found;
|
||||
}
|
||||
if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
}
|
||||
#ifdef JSMN_STRICT
|
||||
/* In strict mode primitive must be followed by a comma/object/array */
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_PART;
|
||||
#endif
|
||||
|
||||
found:
|
||||
if (tokens == NULL) {
|
||||
parser->pos--;
|
||||
return 0;
|
||||
}
|
||||
token = jsmn_alloc_token(parser, tokens, num_tokens);
|
||||
if (token == NULL) {
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_NOMEM;
|
||||
}
|
||||
jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
|
||||
#ifdef JSMN_PARENT_LINKS
|
||||
token->parent = parser->toksuper;
|
||||
#endif
|
||||
parser->pos--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills next token with JSON string.
|
||||
*/
|
||||
static int jsmn_parse_string(jsmn_parser *parser, const char *js,
|
||||
size_t len, jsmntok_t *tokens, size_t num_tokens) {
|
||||
jsmntok_t *token;
|
||||
|
||||
int start = parser->pos;
|
||||
|
||||
parser->pos++;
|
||||
|
||||
/* Skip starting quote */
|
||||
for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
|
||||
char c = js[parser->pos];
|
||||
|
||||
/* Quote: end of string */
|
||||
if (c == '\"') {
|
||||
if (tokens == NULL) {
|
||||
return 0;
|
||||
}
|
||||
token = jsmn_alloc_token(parser, tokens, num_tokens);
|
||||
if (token == NULL) {
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_NOMEM;
|
||||
}
|
||||
jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos);
|
||||
#ifdef JSMN_PARENT_LINKS
|
||||
token->parent = parser->toksuper;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Backslash: Quoted symbol expected */
|
||||
if (c == '\\' && parser->pos + 1 < len) {
|
||||
int i;
|
||||
parser->pos++;
|
||||
switch (js[parser->pos]) {
|
||||
/* Allowed escaped symbols */
|
||||
case '\"': case '/' : case '\\' : case 'b' :
|
||||
case 'f' : case 'r' : case 'n' : case 't' :
|
||||
break;
|
||||
/* Allows escaped symbol \uXXXX */
|
||||
case 'u':
|
||||
parser->pos++;
|
||||
for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) {
|
||||
/* If it isn't a hex character we have an error */
|
||||
if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */
|
||||
(js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */
|
||||
(js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
parser->pos++;
|
||||
}
|
||||
parser->pos--;
|
||||
break;
|
||||
/* Unexpected symbol */
|
||||
default:
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_PART;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse JSON string and fill tokens.
|
||||
*/
|
||||
int jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
|
||||
jsmntok_t *tokens, unsigned int num_tokens) {
|
||||
int r;
|
||||
int i;
|
||||
jsmntok_t *token;
|
||||
int count = parser->toknext;
|
||||
|
||||
for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
|
||||
char c;
|
||||
jsmntype_t type;
|
||||
|
||||
c = js[parser->pos];
|
||||
switch (c) {
|
||||
case '{': case '[':
|
||||
count++;
|
||||
if (tokens == NULL) {
|
||||
break;
|
||||
}
|
||||
token = jsmn_alloc_token(parser, tokens, num_tokens);
|
||||
if (token == NULL)
|
||||
return JSMN_ERROR_NOMEM;
|
||||
if (parser->toksuper != -1) {
|
||||
tokens[parser->toksuper].size++;
|
||||
#ifdef JSMN_PARENT_LINKS
|
||||
token->parent = parser->toksuper;
|
||||
#endif
|
||||
}
|
||||
token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
|
||||
token->start = parser->pos;
|
||||
parser->toksuper = parser->toknext - 1;
|
||||
break;
|
||||
case '}': case ']':
|
||||
if (tokens == NULL)
|
||||
break;
|
||||
type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
|
||||
#ifdef JSMN_PARENT_LINKS
|
||||
if (parser->toknext < 1) {
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
token = &tokens[parser->toknext - 1];
|
||||
for (;;) {
|
||||
if (token->start != -1 && token->end == -1) {
|
||||
if (token->type != type) {
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
token->end = parser->pos + 1;
|
||||
parser->toksuper = token->parent;
|
||||
break;
|
||||
}
|
||||
if (token->parent == -1) {
|
||||
break;
|
||||
}
|
||||
token = &tokens[token->parent];
|
||||
}
|
||||
#else
|
||||
for (i = parser->toknext - 1; i >= 0; i--) {
|
||||
token = &tokens[i];
|
||||
if (token->start != -1 && token->end == -1) {
|
||||
if (token->type != type) {
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
parser->toksuper = -1;
|
||||
token->end = parser->pos + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Error if unmatched closing bracket */
|
||||
if (i == -1) return JSMN_ERROR_INVAL;
|
||||
for (; i >= 0; i--) {
|
||||
token = &tokens[i];
|
||||
if (token->start != -1 && token->end == -1) {
|
||||
parser->toksuper = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case '\"':
|
||||
r = jsmn_parse_string(parser, js, len, tokens, num_tokens);
|
||||
if (r < 0) return r;
|
||||
count++;
|
||||
if (parser->toksuper != -1 && tokens != NULL)
|
||||
tokens[parser->toksuper].size++;
|
||||
break;
|
||||
case '\t' : case '\r' : case '\n' : case ' ':
|
||||
break;
|
||||
case ':':
|
||||
parser->toksuper = parser->toknext - 1;
|
||||
break;
|
||||
case ',':
|
||||
if (tokens != NULL && parser->toksuper != -1 &&
|
||||
tokens[parser->toksuper].type != JSMN_ARRAY &&
|
||||
tokens[parser->toksuper].type != JSMN_OBJECT) {
|
||||
#ifdef JSMN_PARENT_LINKS
|
||||
parser->toksuper = tokens[parser->toksuper].parent;
|
||||
#else
|
||||
for (i = parser->toknext - 1; i >= 0; i--) {
|
||||
if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) {
|
||||
if (tokens[i].start != -1 && tokens[i].end == -1) {
|
||||
parser->toksuper = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
#ifdef JSMN_STRICT
|
||||
/* In strict mode primitives are: numbers and booleans */
|
||||
case '-': case '0': case '1' : case '2': case '3' : case '4':
|
||||
case '5': case '6': case '7' : case '8': case '9':
|
||||
case 't': case 'f': case 'n' :
|
||||
/* And they must not be keys of the object */
|
||||
if (tokens != NULL && parser->toksuper != -1) {
|
||||
jsmntok_t *t = &tokens[parser->toksuper];
|
||||
if (t->type == JSMN_OBJECT ||
|
||||
(t->type == JSMN_STRING && t->size != 0)) {
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* In non-strict mode every unquoted value is a primitive */
|
||||
default:
|
||||
#endif
|
||||
r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens);
|
||||
if (r < 0) return r;
|
||||
count++;
|
||||
if (parser->toksuper != -1 && tokens != NULL)
|
||||
tokens[parser->toksuper].size++;
|
||||
break;
|
||||
|
||||
#ifdef JSMN_STRICT
|
||||
/* Unexpected char in strict mode */
|
||||
default:
|
||||
return JSMN_ERROR_INVAL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (tokens != NULL) {
|
||||
for (i = parser->toknext - 1; i >= 0; i--) {
|
||||
/* Unmatched opened object or array */
|
||||
if (tokens[i].start != -1 && tokens[i].end == -1) {
|
||||
return JSMN_ERROR_PART;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new parser based over a given buffer with an array of tokens
|
||||
* available.
|
||||
*/
|
||||
void jsmn_init(jsmn_parser *parser) {
|
||||
parser->pos = 0;
|
||||
parser->toknext = 0;
|
||||
parser->toksuper = -1;
|
||||
}
|
|
@ -0,0 +1,178 @@
|
|||
set(SRC libsodium/src/libsodium)
|
||||
# Derived from libsodium/src/libsodium/Makefile.am
|
||||
# (ignoring the !MINIMAL set)
|
||||
set(srcs
|
||||
"${SRC}/crypto_aead/chacha20poly1305/sodium/aead_chacha20poly1305.c"
|
||||
"${SRC}/crypto_aead/xchacha20poly1305/sodium/aead_xchacha20poly1305.c"
|
||||
"${SRC}/crypto_auth/crypto_auth.c"
|
||||
"${SRC}/crypto_auth/hmacsha256/auth_hmacsha256.c"
|
||||
"${SRC}/crypto_auth/hmacsha512/auth_hmacsha512.c"
|
||||
"${SRC}/crypto_auth/hmacsha512256/auth_hmacsha512256.c"
|
||||
"${SRC}/crypto_box/crypto_box.c"
|
||||
"${SRC}/crypto_box/crypto_box_easy.c"
|
||||
"${SRC}/crypto_box/crypto_box_seal.c"
|
||||
"${SRC}/crypto_box/curve25519xchacha20poly1305/box_curve25519xchacha20poly1305.c"
|
||||
"${SRC}/crypto_box/curve25519xchacha20poly1305/box_seal_curve25519xchacha20poly1305.c"
|
||||
"${SRC}/crypto_box/curve25519xsalsa20poly1305/box_curve25519xsalsa20poly1305.c"
|
||||
"${SRC}/crypto_core/ed25519/core_ed25519.c"
|
||||
"${SRC}/crypto_core/ed25519/core_ristretto255.c"
|
||||
"${SRC}/crypto_core/ed25519/ref10/ed25519_ref10.c"
|
||||
"${SRC}/crypto_core/hchacha20/core_hchacha20.c"
|
||||
"${SRC}/crypto_core/hsalsa20/core_hsalsa20.c"
|
||||
"${SRC}/crypto_core/hsalsa20/ref2/core_hsalsa20_ref2.c"
|
||||
"${SRC}/crypto_core/salsa/ref/core_salsa_ref.c"
|
||||
"${SRC}/crypto_generichash/blake2b/generichash_blake2.c"
|
||||
"${SRC}/crypto_generichash/blake2b/ref/blake2b-compress-avx2.c"
|
||||
"${SRC}/crypto_generichash/blake2b/ref/blake2b-compress-ref.c"
|
||||
"${SRC}/crypto_generichash/blake2b/ref/blake2b-compress-ssse3.c"
|
||||
"${SRC}/crypto_generichash/blake2b/ref/blake2b-ref.c"
|
||||
"${SRC}/crypto_generichash/blake2b/ref/generichash_blake2b.c"
|
||||
"${SRC}/crypto_generichash/crypto_generichash.c"
|
||||
"${SRC}/crypto_hash/crypto_hash.c"
|
||||
"${SRC}/crypto_hash/sha256/cp/hash_sha256_cp.c"
|
||||
"${SRC}/crypto_hash/sha256/hash_sha256.c"
|
||||
"${SRC}/crypto_hash/sha512/cp/hash_sha512_cp.c"
|
||||
"${SRC}/crypto_hash/sha512/hash_sha512.c"
|
||||
"${SRC}/crypto_kdf/blake2b/kdf_blake2b.c"
|
||||
"${SRC}/crypto_kdf/crypto_kdf.c"
|
||||
"${SRC}/crypto_kx/crypto_kx.c"
|
||||
"${SRC}/crypto_onetimeauth/crypto_onetimeauth.c"
|
||||
"${SRC}/crypto_onetimeauth/poly1305/donna/poly1305_donna.c"
|
||||
"${SRC}/crypto_onetimeauth/poly1305/onetimeauth_poly1305.c"
|
||||
"${SRC}/crypto_pwhash/argon2/argon2-core.c"
|
||||
"${SRC}/crypto_pwhash/argon2/argon2-encoding.c"
|
||||
"${SRC}/crypto_pwhash/argon2/argon2-fill-block-avx2.c"
|
||||
"${SRC}/crypto_pwhash/argon2/argon2-fill-block-avx512f.c"
|
||||
"${SRC}/crypto_pwhash/argon2/argon2-fill-block-ref.c"
|
||||
"${SRC}/crypto_pwhash/argon2/argon2-fill-block-ssse3.c"
|
||||
"${SRC}/crypto_pwhash/argon2/argon2.c"
|
||||
"${SRC}/crypto_pwhash/argon2/blake2b-long.c"
|
||||
"${SRC}/crypto_pwhash/argon2/pwhash_argon2i.c"
|
||||
"${SRC}/crypto_pwhash/argon2/pwhash_argon2id.c"
|
||||
"${SRC}/crypto_pwhash/crypto_pwhash.c"
|
||||
"${SRC}/crypto_pwhash/scryptsalsa208sha256/crypto_scrypt-common.c"
|
||||
"${SRC}/crypto_pwhash/scryptsalsa208sha256/nosse/pwhash_scryptsalsa208sha256_nosse.c"
|
||||
"${SRC}/crypto_pwhash/scryptsalsa208sha256/pbkdf2-sha256.c"
|
||||
"${SRC}/crypto_pwhash/scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c"
|
||||
"${SRC}/crypto_pwhash/scryptsalsa208sha256/scrypt_platform.c"
|
||||
"${SRC}/crypto_scalarmult/crypto_scalarmult.c"
|
||||
"${SRC}/crypto_scalarmult/curve25519/ref10/x25519_ref10.c"
|
||||
"${SRC}/crypto_scalarmult/curve25519/sandy2x/consts.S"
|
||||
"${SRC}/crypto_scalarmult/curve25519/sandy2x/curve25519_sandy2x.c"
|
||||
"${SRC}/crypto_scalarmult/curve25519/sandy2x/fe51_invert.c"
|
||||
"${SRC}/crypto_scalarmult/curve25519/sandy2x/fe51_mul.S"
|
||||
"${SRC}/crypto_scalarmult/curve25519/sandy2x/fe51_nsquare.S"
|
||||
"${SRC}/crypto_scalarmult/curve25519/sandy2x/fe51_pack.S"
|
||||
"${SRC}/crypto_scalarmult/curve25519/sandy2x/fe_frombytes_sandy2x.c"
|
||||
"${SRC}/crypto_scalarmult/curve25519/sandy2x/ladder.S"
|
||||
"${SRC}/crypto_scalarmult/curve25519/sandy2x/sandy2x.S"
|
||||
"${SRC}/crypto_scalarmult/curve25519/scalarmult_curve25519.c"
|
||||
"${SRC}/crypto_scalarmult/ed25519/ref10/scalarmult_ed25519_ref10.c"
|
||||
"${SRC}/crypto_scalarmult/ristretto255/ref10/scalarmult_ristretto255_ref10.c"
|
||||
"${SRC}/crypto_secretbox/crypto_secretbox.c"
|
||||
"${SRC}/crypto_secretbox/crypto_secretbox_easy.c"
|
||||
"${SRC}/crypto_secretbox/xchacha20poly1305/secretbox_xchacha20poly1305.c"
|
||||
"${SRC}/crypto_secretbox/xsalsa20poly1305/secretbox_xsalsa20poly1305.c"
|
||||
"${SRC}/crypto_secretstream/xchacha20poly1305/secretstream_xchacha20poly1305.c"
|
||||
"${SRC}/crypto_shorthash/crypto_shorthash.c"
|
||||
"${SRC}/crypto_shorthash/siphash24/ref/shorthash_siphash24_ref.c"
|
||||
"${SRC}/crypto_shorthash/siphash24/ref/shorthash_siphashx24_ref.c"
|
||||
"${SRC}/crypto_shorthash/siphash24/shorthash_siphash24.c"
|
||||
"${SRC}/crypto_shorthash/siphash24/shorthash_siphashx24.c"
|
||||
"${SRC}/crypto_sign/crypto_sign.c"
|
||||
"${SRC}/crypto_sign/ed25519/ref10/keypair.c"
|
||||
"${SRC}/crypto_sign/ed25519/ref10/obsolete.c"
|
||||
"${SRC}/crypto_sign/ed25519/ref10/open.c"
|
||||
"${SRC}/crypto_sign/ed25519/ref10/sign.c"
|
||||
"${SRC}/crypto_sign/ed25519/sign_ed25519.c"
|
||||
"${SRC}/crypto_stream/chacha20/dolbeau/chacha20_dolbeau-avx2.c"
|
||||
"${SRC}/crypto_stream/chacha20/dolbeau/chacha20_dolbeau-ssse3.c"
|
||||
"${SRC}/crypto_stream/chacha20/ref/chacha20_ref.c"
|
||||
"${SRC}/crypto_stream/chacha20/stream_chacha20.c"
|
||||
"${SRC}/crypto_stream/crypto_stream.c"
|
||||
"${SRC}/crypto_stream/salsa20/ref/salsa20_ref.c"
|
||||
"${SRC}/crypto_stream/salsa20/stream_salsa20.c"
|
||||
"${SRC}/crypto_stream/salsa20/xmm6/salsa20_xmm6-asm.S"
|
||||
"${SRC}/crypto_stream/salsa20/xmm6/salsa20_xmm6.c"
|
||||
"${SRC}/crypto_stream/salsa20/xmm6int/salsa20_xmm6int-avx2.c"
|
||||
"${SRC}/crypto_stream/salsa20/xmm6int/salsa20_xmm6int-sse2.c"
|
||||
"${SRC}/crypto_stream/salsa2012/ref/stream_salsa2012_ref.c"
|
||||
"${SRC}/crypto_stream/salsa2012/stream_salsa2012.c"
|
||||
"${SRC}/crypto_stream/salsa208/ref/stream_salsa208_ref.c"
|
||||
"${SRC}/crypto_stream/salsa208/stream_salsa208.c"
|
||||
"${SRC}/crypto_stream/xchacha20/stream_xchacha20.c"
|
||||
"${SRC}/crypto_stream/xsalsa20/stream_xsalsa20.c"
|
||||
"${SRC}/crypto_verify/sodium/verify.c"
|
||||
"${SRC}/randombytes/randombytes.c"
|
||||
"${SRC}/sodium/codecs.c"
|
||||
"${SRC}/sodium/core.c"
|
||||
"${SRC}/sodium/runtime.c"
|
||||
"${SRC}/sodium/utils.c"
|
||||
"${SRC}/sodium/version.c"
|
||||
"port/randombytes_esp32.c")
|
||||
|
||||
if(CONFIG_LIBSODIUM_USE_MBEDTLS_SHA)
|
||||
list(APPEND srcs
|
||||
"port/crypto_hash_mbedtls/crypto_hash_sha256_mbedtls.c"
|
||||
"port/crypto_hash_mbedtls/crypto_hash_sha512_mbedtls.c")
|
||||
else()
|
||||
list(APPEND srcs
|
||||
"${SRC}/crypto_hash/sha256/cp/hash_sha256_cp.c"
|
||||
"${SRC}/crypto_hash/sha512/cp/hash_sha512_cp.c")
|
||||
endif()
|
||||
|
||||
set(include_dirs ${SRC}/include port_include)
|
||||
set(priv_include_dirs ${SRC}/include/sodium port_include/sodium port)
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
INCLUDE_DIRS "${include_dirs}"
|
||||
PRIV_INCLUDE_DIRS "${priv_include_dirs}"
|
||||
REQUIRES mbedtls)
|
||||
|
||||
target_compile_definitions(${COMPONENT_LIB} PRIVATE
|
||||
CONFIGURED
|
||||
NATIVE_LITTLE_ENDIAN
|
||||
HAVE_WEAK_SYMBOLS
|
||||
__STDC_LIMIT_MACROS
|
||||
__STDC_CONSTANT_MACROS
|
||||
)
|
||||
|
||||
# patch around warnings in third-party files
|
||||
set_source_files_properties(
|
||||
${SRC}/crypto_pwhash/argon2/pwhash_argon2i.c
|
||||
${SRC}/crypto_pwhash/argon2/pwhash_argon2id.c
|
||||
${SRC}/crypto_pwhash/argon2/argon2-core.c
|
||||
${SRC}/crypto_pwhash/scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c
|
||||
PROPERTIES COMPILE_FLAGS
|
||||
-Wno-type-limits
|
||||
)
|
||||
set_source_files_properties(
|
||||
${SRC}/sodium/utils.c
|
||||
PROPERTIES COMPILE_FLAGS
|
||||
-Wno-unused-variable
|
||||
)
|
||||
set_source_files_properties(
|
||||
${SRC}/crypto_pwhash/argon2/argon2-fill-block-ref.c
|
||||
PROPERTIES COMPILE_FLAGS
|
||||
-Wno-unknown-pragmas
|
||||
)
|
||||
|
||||
# Temporary suppress "fallthrough" warnings until they are fixed in libsodium repo
|
||||
set_source_files_properties(
|
||||
${SRC}/crypto_shorthash/siphash24/ref/shorthash_siphashx24_ref.c
|
||||
${SRC}/crypto_shorthash/siphash24/ref/shorthash_siphash24_ref.c
|
||||
PROPERTIES COMPILE_FLAGS
|
||||
-Wno-implicit-fallthrough
|
||||
)
|
||||
|
||||
set_source_files_properties(
|
||||
${SRC}/randombytes/randombytes.c
|
||||
PROPERTIES COMPILE_FLAGS
|
||||
-DRANDOMBYTES_DEFAULT_IMPLEMENTATION
|
||||
)
|
||||
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-unused-function)
|
||||
|
||||
if(CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE)
|
||||
# some libsodium variables are only used for asserts
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-unused-but-set-variable)
|
||||
endif()
|
|
@ -0,0 +1,15 @@
|
|||
menu "libsodium"
|
||||
|
||||
config LIBSODIUM_USE_MBEDTLS_SHA
|
||||
bool "Use mbedTLS SHA256 & SHA512 implementations"
|
||||
default y
|
||||
depends on !MBEDTLS_HARDWARE_SHA
|
||||
help
|
||||
If this option is enabled, libsodium will use thin wrappers
|
||||
around mbedTLS for SHA256 & SHA512 operations.
|
||||
|
||||
This saves some code size if mbedTLS is also used. However it
|
||||
is incompatible with hardware SHA acceleration (due to the
|
||||
way libsodium's API manages SHA state).
|
||||
|
||||
endmenu # libsodium
|
|
@ -0,0 +1 @@
|
|||
libsodium/LICENSE
|
|
@ -0,0 +1 @@
|
|||
libsodium/README.markdown
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
version: "1.0.18"
|
||||
description: libsodium port to ESP32
|
||||
url: https://github.com/espressif/idf-extra-components/tree/master/libsodium
|
||||
dependencies:
|
||||
idf: ">=4.2"
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 4f5e89fa84ce1d178a6765b8b46f2b6f91216677
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "crypto_hash_sha256.h"
|
||||
#include "mbedtls/sha256.h"
|
||||
#include <string.h>
|
||||
|
||||
#ifdef MBEDTLS_SHA256_ALT
|
||||
/* Wrapper only works if the libsodium context structure can be mapped
|
||||
directly to the mbedTLS context structure.
|
||||
|
||||
See extended comments in crypto_hash_sha512_mbedtls.c
|
||||
*/
|
||||
#error "This wrapper only support standard software mbedTLS SHA"
|
||||
#endif
|
||||
|
||||
/* Sanity check that all the context fields have identical sizes
|
||||
(this should be more or less given from the SHA256 algorithm)
|
||||
|
||||
Note that the meaning of the fields is *not* all the same. In libsodium, SHA256 'count' is a 64-bit *bit* count. In
|
||||
mbedTLS, 'total' is a 2x32-bit *byte* count (count[0] == MSB).
|
||||
|
||||
For this implementation, we don't convert so the libsodium state structure actually holds a binary copy of the
|
||||
mbedTLS totals. This doesn't matter inside libsodium's documented API, but would matter if any callers try to use
|
||||
the state's bit count.
|
||||
*/
|
||||
_Static_assert(sizeof(((crypto_hash_sha256_state *)0)->state) == sizeof(((mbedtls_sha256_context *)0)->state), "state mismatch");
|
||||
_Static_assert(sizeof(((crypto_hash_sha256_state *)0)->count) == sizeof(((mbedtls_sha256_context *)0)->total), "count mismatch");
|
||||
_Static_assert(sizeof(((crypto_hash_sha256_state *)0)->buf) == sizeof(((mbedtls_sha256_context *)0)->buffer), "buf mismatch");
|
||||
|
||||
/* Inline functions to convert between mbedTLS & libsodium
|
||||
context structures
|
||||
*/
|
||||
|
||||
static void sha256_mbedtls_to_libsodium(crypto_hash_sha256_state *ls_state, const mbedtls_sha256_context *mb_ctx)
|
||||
{
|
||||
memcpy(&ls_state->count, mb_ctx->total, sizeof(ls_state->count));
|
||||
memcpy(ls_state->state, mb_ctx->state, sizeof(ls_state->state));
|
||||
memcpy(ls_state->buf, mb_ctx->buffer, sizeof(ls_state->buf));
|
||||
}
|
||||
|
||||
static void sha256_libsodium_to_mbedtls(mbedtls_sha256_context *mb_ctx, crypto_hash_sha256_state *ls_state)
|
||||
{
|
||||
memcpy(mb_ctx->total, &ls_state->count, sizeof(mb_ctx->total));
|
||||
memcpy(mb_ctx->state, ls_state->state, sizeof(mb_ctx->state));
|
||||
memcpy(mb_ctx->buffer, ls_state->buf, sizeof(mb_ctx->buffer));
|
||||
mb_ctx->is224 = 0;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_hash_sha256_init(crypto_hash_sha256_state *state)
|
||||
{
|
||||
mbedtls_sha256_context ctx;
|
||||
mbedtls_sha256_init(&ctx);
|
||||
int ret = mbedtls_sha256_starts_ret(&ctx, 0);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
sha256_mbedtls_to_libsodium(state, &ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_hash_sha256_update(crypto_hash_sha256_state *state,
|
||||
const unsigned char *in, unsigned long long inlen)
|
||||
{
|
||||
mbedtls_sha256_context ctx;
|
||||
sha256_libsodium_to_mbedtls(&ctx, state);
|
||||
int ret = mbedtls_sha256_update_ret(&ctx, in, inlen);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
sha256_mbedtls_to_libsodium(state, &ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_hash_sha256_final(crypto_hash_sha256_state *state, unsigned char *out)
|
||||
{
|
||||
mbedtls_sha256_context ctx;
|
||||
sha256_libsodium_to_mbedtls(&ctx, state);
|
||||
return mbedtls_sha256_finish_ret(&ctx, out);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_hash_sha256(unsigned char *out, const unsigned char *in,
|
||||
unsigned long long inlen)
|
||||
{
|
||||
return mbedtls_sha256_ret(in, inlen, out, 0);
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "crypto_hash_sha512.h"
|
||||
#include "mbedtls/sha512.h"
|
||||
#include <string.h>
|
||||
|
||||
#ifdef MBEDTLS_SHA512_ALT
|
||||
/* Wrapper only works if the libsodium context structure can be mapped
|
||||
directly to the mbedTLS context structure.
|
||||
|
||||
For ESP32 hardware SHA, the problems are fitting all the data in
|
||||
the libsodium state structure, and also that libsodium doesn't
|
||||
have mbedtls_sha512_free() or mbedtls_sha512_clone() so we can't
|
||||
manage the hardware state in a clean way.
|
||||
*/
|
||||
#error "This wrapper only support standard software mbedTLS SHA"
|
||||
#endif
|
||||
|
||||
/* Sanity check that all the context fields have identical sizes
|
||||
(this should be more or less given from the SHA512 algorithm)
|
||||
|
||||
Note that the meaning of the fields is *not* all the same. In libsodium,
|
||||
SHA512 'count' is a 2xuin64_t *bit* count where count[0] == MSB. In mbedTLS,
|
||||
SHA512 'total' is a 2xuint64_t *byte* count where count[0] == LSB.
|
||||
|
||||
For this implementation, we don't convert so the libsodium state structure actually holds a binary copy of the
|
||||
mbedTLS totals. This doesn't matter inside libsodium's documented API, but would matter if any callers try to use
|
||||
the state's bit count.
|
||||
*/
|
||||
_Static_assert(sizeof(((crypto_hash_sha512_state *)0)->state) == sizeof(((mbedtls_sha512_context *)0)->state), "state mismatch");
|
||||
_Static_assert(sizeof(((crypto_hash_sha512_state *)0)->count) == sizeof(((mbedtls_sha512_context *)0)->total), "count mismatch");
|
||||
_Static_assert(sizeof(((crypto_hash_sha512_state *)0)->buf) == sizeof(((mbedtls_sha512_context *)0)->buffer), "buf mismatch");
|
||||
|
||||
/* Inline functions to convert between mbedTLS & libsodium
|
||||
context structures
|
||||
*/
|
||||
|
||||
static void sha512_mbedtls_to_libsodium(crypto_hash_sha512_state *ls_state, const mbedtls_sha512_context *mb_ctx)
|
||||
{
|
||||
memcpy(ls_state->count, mb_ctx->total, sizeof(ls_state->count));
|
||||
memcpy(ls_state->state, mb_ctx->state, sizeof(ls_state->state));
|
||||
memcpy(ls_state->buf, mb_ctx->buffer, sizeof(ls_state->buf));
|
||||
}
|
||||
|
||||
static void sha512_libsodium_to_mbedtls(mbedtls_sha512_context *mb_ctx, crypto_hash_sha512_state *ls_state)
|
||||
{
|
||||
memcpy(mb_ctx->total, ls_state->count, sizeof(mb_ctx->total));
|
||||
memcpy(mb_ctx->state, ls_state->state, sizeof(mb_ctx->state));
|
||||
memcpy(mb_ctx->buffer, ls_state->buf, sizeof(mb_ctx->buffer));
|
||||
mb_ctx->is384 = 0;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_hash_sha512_init(crypto_hash_sha512_state *state)
|
||||
{
|
||||
mbedtls_sha512_context ctx;
|
||||
mbedtls_sha512_init(&ctx);
|
||||
int ret = mbedtls_sha512_starts_ret(&ctx, 0);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
sha512_mbedtls_to_libsodium(state, &ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_hash_sha512_update(crypto_hash_sha512_state *state,
|
||||
const unsigned char *in, unsigned long long inlen)
|
||||
{
|
||||
mbedtls_sha512_context ctx;
|
||||
sha512_libsodium_to_mbedtls(&ctx, state);
|
||||
int ret = mbedtls_sha512_update_ret(&ctx, in, inlen);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
sha512_mbedtls_to_libsodium(state, &ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_hash_sha512_final(crypto_hash_sha512_state *state, unsigned char *out)
|
||||
{
|
||||
mbedtls_sha512_context ctx;
|
||||
sha512_libsodium_to_mbedtls(&ctx, state);
|
||||
return mbedtls_sha512_finish_ret(&ctx, out);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_hash_sha512(unsigned char *out, const unsigned char *in,
|
||||
unsigned long long inlen)
|
||||
{
|
||||
return mbedtls_sha512_ret(in, inlen, out, 0);
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "randombytes_internal.h"
|
||||
#include "esp_system.h"
|
||||
|
||||
static const char *randombytes_esp32xx_implementation_name(void)
|
||||
{
|
||||
return CONFIG_IDF_TARGET;
|
||||
}
|
||||
|
||||
/*
|
||||
Plug the ESP32 hardware RNG into libsodium's custom RNG support, as per
|
||||
https://download.libsodium.org/doc/advanced/custom_rng.html
|
||||
|
||||
Note that this RNG is selected by default (see randombytes_default.h), so there
|
||||
is no need to call randombytes_set_implementation().
|
||||
*/
|
||||
const struct randombytes_implementation randombytes_esp32_implementation = {
|
||||
.implementation_name = randombytes_esp32xx_implementation_name,
|
||||
.random = esp_random,
|
||||
.stir = NULL,
|
||||
.uniform = NULL,
|
||||
.buf = esp_fill_random,
|
||||
.close = NULL,
|
||||
};
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
# include "export.h"
|
||||
# include "randombytes.h"
|
||||
|
||||
SODIUM_EXPORT
|
||||
extern const struct randombytes_implementation randombytes_esp32_implementation;
|
||||
|
||||
/* Defining RANDOMBYTES_DEFAULT_IMPLEMENTATION here allows us to compile with the ESP32 hardware
|
||||
implementation as the default. No need to call randombytes_set_implementation().
|
||||
|
||||
Doing it in the header like this is easier than passing it via a -D argument to gcc.
|
||||
*/
|
||||
#undef RANDOMBYTES_DEFAULT_IMPLEMENTATION
|
||||
#define RANDOMBYTES_DEFAULT_IMPLEMENTATION &randombytes_esp32_implementation
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef sodium_version_H
|
||||
#define sodium_version_H
|
||||
|
||||
#include <sodium/export.h>
|
||||
|
||||
/* IMPORTANT: As we don't use autotools, these version are not automatically
|
||||
updated if we change submodules. They need to be changed manually.
|
||||
*/
|
||||
|
||||
#define SODIUM_VERSION_STRING "1.0.18-idf"
|
||||
|
||||
/* Note: these are not the same as the overall version, see
|
||||
configure.ac for the relevant macros */
|
||||
#define SODIUM_LIBRARY_VERSION_MAJOR 10
|
||||
#define SODIUM_LIBRARY_VERSION_MINOR 3
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
SODIUM_EXPORT
|
||||
const char *sodium_version_string(void);
|
||||
|
||||
SODIUM_EXPORT
|
||||
int sodium_library_version_major(void);
|
||||
|
||||
SODIUM_EXPORT
|
||||
int sodium_library_version_minor(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,36 @@
|
|||
if(TESTS_ALL EQUAL 1)
|
||||
message("not linking libsodium tests, use '-T libsodium' to test it")
|
||||
else()
|
||||
get_filename_component(LS_TESTDIR "${CMAKE_CURRENT_LIST_DIR}/../libsodium/test/default" ABSOLUTE)
|
||||
|
||||
set(TEST_CASES "chacha20;aead_chacha20poly1305;box;box2;ed25519_convert;sign;hash")
|
||||
|
||||
foreach(test_case ${TEST_CASES})
|
||||
file(GLOB test_case_file "${LS_TESTDIR}/${test_case}.c")
|
||||
list(APPEND TEST_CASES_FILES ${test_case_file})
|
||||
endforeach()
|
||||
|
||||
idf_component_register(SRCS "${TEST_CASES_FILES}" "test_sodium.c"
|
||||
PRIV_INCLUDE_DIRS "." "${LS_TESTDIR}/../quirks"
|
||||
PRIV_REQUIRES cmock libsodium)
|
||||
|
||||
# The libsodium test suite is designed to be run each test case as an executable on a desktop computer and uses
|
||||
# filesytem to write & then compare contents of each file.
|
||||
#
|
||||
# For now, use their "BROWSER_TEST" mode with these hacks so that
|
||||
# multiple test cases can be combined into one ELF file.
|
||||
#
|
||||
# Run each test case from test_sodium.c as CASENAME_xmain().
|
||||
foreach(test_case_file ${TEST_CASES_FILES})
|
||||
get_filename_component(test_case ${test_case_file} NAME_WE)
|
||||
set_source_files_properties(${test_case_file}
|
||||
PROPERTIES COMPILE_FLAGS
|
||||
# This would generate 'warning "main" redefined' warnings at runtime, which are
|
||||
# silenced here. Only other solution involves patching libsodium's cmptest.h.
|
||||
"-Dxmain=${test_case}_xmain -Dmain=${test_case}_main -Wp,-w")
|
||||
endforeach()
|
||||
|
||||
# this seems odd, but it prevents the libsodium test harness from
|
||||
# trying to write to a file!
|
||||
add_definitions(-DBROWSER_TESTS)
|
||||
endif()
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "unity.h"
|
||||
#include "sodium/crypto_hash_sha256.h"
|
||||
#include "sodium/crypto_hash_sha512.h"
|
||||
|
||||
/* Note: a lot of these libsodium test programs assert() things, but they're not complete unit tests - most expect
|
||||
output to be compared to the matching .exp file.
|
||||
|
||||
We don't do this automatically yet, maybe once we have more options for
|
||||
internal filesystem storage.
|
||||
*/
|
||||
|
||||
extern int aead_chacha20poly1305_xmain(void);
|
||||
|
||||
TEST_CASE("aead_chacha20poly1305 test vectors", "[libsodium]")
|
||||
{
|
||||
printf("Running aead_chacha20poly1305\n");
|
||||
TEST_ASSERT_EQUAL(0, aead_chacha20poly1305_xmain());
|
||||
}
|
||||
|
||||
extern int chacha20_xmain(void);
|
||||
|
||||
TEST_CASE("chacha20 test vectors", "[libsodium]")
|
||||
{
|
||||
printf("Running chacha20\n");
|
||||
TEST_ASSERT_EQUAL(0, chacha20_xmain());
|
||||
}
|
||||
|
||||
extern int box_xmain(void);
|
||||
extern int box2_xmain(void);
|
||||
|
||||
TEST_CASE("box tests", "[libsodium]")
|
||||
{
|
||||
printf("Running box\n");
|
||||
TEST_ASSERT_EQUAL(0, box_xmain());
|
||||
|
||||
printf("Running box2\n");
|
||||
TEST_ASSERT_EQUAL(0, box2_xmain());
|
||||
}
|
||||
|
||||
extern int ed25519_convert_xmain(void);
|
||||
|
||||
TEST_CASE("ed25519_convert tests", "[libsodium][timeout=60]")
|
||||
{
|
||||
printf("Running ed25519_convert\n");
|
||||
TEST_ASSERT_EQUAL(0, ed25519_convert_xmain() );
|
||||
}
|
||||
|
||||
extern int sign_xmain(void);
|
||||
|
||||
TEST_CASE("sign tests", "[libsodium]")
|
||||
{
|
||||
printf("Running sign\n");
|
||||
TEST_ASSERT_EQUAL(0, sign_xmain() );
|
||||
}
|
||||
|
||||
extern int hash_xmain(void);
|
||||
|
||||
TEST_CASE("hash tests", "[libsodium]")
|
||||
{
|
||||
printf("Running hash\n");
|
||||
TEST_ASSERT_EQUAL(0, hash_xmain() );
|
||||
}
|
||||
|
||||
TEST_CASE("sha256 sanity check", "[libsodium]")
|
||||
{
|
||||
const uint8_t expected[] = { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41,
|
||||
0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03,
|
||||
0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, 0xb4, 0x10, 0xff,
|
||||
0x61, 0xf2, 0x00, 0x15, 0xad, };
|
||||
uint8_t calculated[32];
|
||||
crypto_hash_sha256_state state;
|
||||
|
||||
const uint8_t *in = (const uint8_t *)"abc";
|
||||
const size_t inlen = 3;
|
||||
|
||||
// One-liner version
|
||||
crypto_hash_sha256(calculated, in, inlen);
|
||||
TEST_ASSERT_EQUAL(sizeof(calculated), sizeof(expected));
|
||||
TEST_ASSERT_EQUAL(sizeof(calculated), crypto_hash_sha256_bytes());
|
||||
TEST_ASSERT_EQUAL_MEMORY(expected, calculated, crypto_hash_sha256_bytes());
|
||||
|
||||
// Multi-line version
|
||||
crypto_hash_sha256_init(&state);
|
||||
crypto_hash_sha256_update(&state, in, inlen - 1); // split into two updates
|
||||
crypto_hash_sha256_update(&state, in + (inlen -1), 1);
|
||||
crypto_hash_sha256_final(&state, calculated);
|
||||
TEST_ASSERT_EQUAL_MEMORY(expected, calculated, crypto_hash_sha256_bytes());
|
||||
}
|
||||
|
||||
TEST_CASE("sha512 sanity check", "[libsodium]")
|
||||
{
|
||||
const uint8_t expected[] = { 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, 0xcc,
|
||||
0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31, 0x12, 0xe6,
|
||||
0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, 0x0a, 0x9e, 0xee,
|
||||
0xe6, 0x4b, 0x55, 0xd3, 0x9a, 0x21, 0x92, 0x99, 0x2a,
|
||||
0x27, 0x4f, 0xc1, 0xa8, 0x36, 0xba, 0x3c, 0x23, 0xa3,
|
||||
0xfe, 0xeb, 0xbd, 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c,
|
||||
0xe8, 0x0e, 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4,
|
||||
0x9f };
|
||||
|
||||
uint8_t calculated[64];
|
||||
crypto_hash_sha512_state state;
|
||||
|
||||
const uint8_t *in = (const uint8_t *)"abc";
|
||||
const size_t inlen = 3;
|
||||
|
||||
// One-liner version
|
||||
crypto_hash_sha512(calculated, in, inlen);
|
||||
TEST_ASSERT_EQUAL(sizeof(calculated), sizeof(expected));
|
||||
TEST_ASSERT_EQUAL(sizeof(calculated), crypto_hash_sha512_bytes());
|
||||
TEST_ASSERT_EQUAL_MEMORY(expected, calculated, crypto_hash_sha512_bytes());
|
||||
|
||||
// Multi-line version
|
||||
crypto_hash_sha512_init(&state);
|
||||
crypto_hash_sha512_update(&state, in, inlen - 1); // split into two updates
|
||||
crypto_hash_sha512_update(&state, in + (inlen -1), 1);
|
||||
crypto_hash_sha512_final(&state, calculated);
|
||||
TEST_ASSERT_EQUAL_MEMORY(expected, calculated, crypto_hash_sha512_bytes());
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
version: "0.1.0"
|
||||
description: Proportional-integral-derivative controller
|
||||
url: https://github.com/espressif/idf-extra-components/tree/master/pid_ctrl
|
||||
dependencies:
|
||||
idf: ">=4.3"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
version: "0.1.0"
|
||||
description: QR Code generator
|
||||
url: https://github.com/espressif/idf-extra-components/tree/master/qr_code
|
||||
dependencies:
|
||||
idf: ">=4.3"
|
||||
|
|
Loading…
Reference in New Issue