General information
This section describes basic and general information regards API references, access control, response and error codes.

Operational security basics

Here are a few steps the developer should follow to achieve proper operation security of the Encedo HEM:
  • First and foremost DO NOT leave your Encedo HEM unattended. We did our best to secure the device but the other side may have a multi-million dollar budget to break in. Do not make their lives easy by:
    • making the Encedo PPA a personal device, attach it to the keychain or so;
    • installing Encedo EPA in a professional data centre or server room with controlled and limited physical access.
  • Always check the security of the TLS connection, do not ignore warnings or any other issues with TLS session security. This is critical to achieving the confidentiality of your data (e.g. during encryption/decryption) and of the JWT tokens. The consequences of leaked tokens can be tragic!
  • If your application is using passphrase-based user authentication (user password) keep the runtime environment secure. Do not store passwords in the code (hardcoding)! For web apps remember that some browser plugins can record keystrokes and steal your password. Use the free Encedo Mobile AUthenticator over passwords if possible.
  • Check the logs from time to time :) The logging mechanism of every security-related activity by Encedo HEM is a very powerful feature. Consider deep integration of the Encedo HEM logs with SIEM or other automated security monitoring tools.

How to read API references?

Encedo HEM implements a classic CRUD (create-read-update-delete) type of API, RESTful HTTP(s) based API.
The API supports both HTTP (port 80) and HTTPS (port 443) protocols. However, some operations are limited to the HTTPS interface only. In general, all operations with access control are limited to HTTPS only.
The API parameters, send as body parameters, are represented via JSON objects with the required "application/json" Content-Type header send altogether. The reply (response body) is also a JSON encoded object. The missing Content-Type header will fail the API call.
On factory-default (so-called 'fresh', not initialised) devices firmware and management applications can be upgraded over HTTP interface, This is possible due to the fact the uploaded file is digitally signed and before the installation, the integrity and the signature will be validated.
The API is stateless.
All API reference endpoints refer to a domain my.ence.do. This domain is a default domain for Encedo PPA and is used here as a reference. After personalization, the device might be available under custom domains, as regards user preferences.

Access to the device

Depending on the version (Encedo PPA or EPA), access to the device is slightly different. In both cases, it is the same web API (EPA do not have a few endpoints as noted in the API Reference), but the domain is different.
The Encedo PPA in the factory default state (fresh, just delivered or after wipe-out) serves API over domain my.ence.do resolve to the IP address 192.168.7.1.
The Encedo EPA (delivered for on-premises installations) in the factory default stated is available under the technical domain presented in the Delivery Note. Assume the Delivery Note states in section Setup Details the technical domain is *.e400123-a1.cloud.ence.do for node A1, the Encedo HEM (chips) are accessible under domains c1.e400123-a1.cloud.ence.do to c10.e400123-a1.cloud.ence.do. For node B2 it will be e.g. c1.e400123-b2.cloud.ence.do.
The Encedo EPA subscribed in a SaaS model (user can get access to just one HEM chip) will present the configuration (and domain) in the email sent to the buyer as a summary of the subscription.
After the device is initialized, it will be available under the domain selected by the user during the initilization procedure.

Troubleshooting

If you encounter any troubles using API, read the API reference carefully. The response code may say a lot :)
The first stop should be endpoint Get Status. It will say e.g. if the RTC is set (object ts returned) as it is required by authentication. Also, note the value of the fls_state object; any non-zero value means the Encedo HEM is in a failed state. Check the reason for the failure here.
The second stop should test if the TLS server is working. The certificate may expire if the device is not used for longer. The renewal process is automatic. All you need is to perform a complete check-in procedure and reboot the HEM (called over HTTP protocol).
Encedo PPA users can use the online wizard available here: https://encedo.com/rescue/ and follow the instructions.

What is a check-in procedure?

The check-in process is a simple challenge-response protocol between the Device (issuer of the challenge message) and the Backend (issuer of the response message). The idea for this process is as follows:
  • the device needs a trusted source of the real-time clock (RTC) a'ka trusted source of time;
  • the device stores (as trusted) the list of backend public keys so it's able to validate the response (the integrity and origin),
  • the backend can send information about new firmware version availability,
  • updated x509 TLS certificate can be sent over;
  • it is possible to implement Remote Management;
  • the process was designed with privacy-focused
For daily usage, the primary purpose of this procedure is to set up a Real-Time Clock (RTC) inside the device. The time is unknown after every powerup (or reboot) of the device but is critical for authentication. So the application should check if an RTC is set, if not - the API will return 403 on every authentication call.

Privacy notes

The check-in process was designed with privacy in mind. The backend is unable to trace the device in any domain. Every transaction (check -> checked) is anonymous from the backend point of view.
The mechanism IS able to offer enterprise-level of remote management of the devices deployed in the organization. Remote management is based on uploading the instanceid value uniquely identifying every instance of Encedo HEM (instanceid is generated as a result of personalization).
Example check check-in challenge string (after decoded):
# header
{
"ecdh": "x25519",
"typ": "JWT",
"alg": "HS256"
}
# body
{
"jti": "kIA3YrCAbi1vCU1h8ypn2Kts1QSDOQUKNsaUIgWoSr0=",
"iss": "0kRmCliUQvRwfxi7T1ek2GtbSERzMFRGLeyO1r1tEXo=",
"qid": "e6PAvCZrmMc0fUT0KzmL7I3TIz6QFA4JBjYslE9f+/A=",
"aud": "/Lbxo5MgU6ZOtVsxxG5jCQ5+4ewxoa1rV8eqMIFFnTA=",
"fws": "Z+kAajgVVdSMQjNIvK5FGz0+9rf/JutVClNY6S7GBeQ765NMYET/XgdA61cmMk15waw08oNLuWmUygHK3xWFCA==",
"bls": "8MwowsKkxgEWnl2k0t/eOvsjTbR70poYC2czyPIwKn/hVL68WF3QaQwZ1bxVcYv7g8WEwyzJ2PVnTFAlYQ7hBg==",
"uis": "6Gh2cCqSJ0GULQKE1DiboY1OsC8rM5+1xPZclCnhtro=",
"csn": "KfsaKKvNl4LvPigl0GmGBg=="
}
# signature
<base64 encoded SHA256 hash>
Example checked check-in reply string:
# header
{
"ecdh": "x25519",
"typ": "JWT",
"alg": "HS256"
}
# body
{
"jti": "FBJDYuJoh+kIpLRTE1IV6/KMNBslpbbH72Jd9ZlX3C0=",
"iat": 1648562709,
"iss": "/Lbxo5MgU6ZOtVsxxG5jCQ5+4ewxoa1rV8eqMIFFnTA=",
"aud": "2xwbMkO0QScPojImeHgpi3k3WhnyhdVyiL7iWkGb5kw=",
"status": "VKn3hqKX2WR37rsvGnNYKs3FscMxw9uqVF/JhtHUen0="
}
# signature
<base64 encoded SHA256 hash>

User, rules and access scope

There are three user roles, each with different access role and limitations:
User
Master
ExtAuth
Local User: A regular passphrase based authenticated user, general usage.
Administrator: Master user, limited usage to rescue purposes.,
Remote User: A user authenticated by an external authenticator (e.g. Encedo Mobile AUthenticator available on Google Play and Apple AppStore).
Check the API Reference section for more details about when and how user roles enter the game for each and every endpoint. Rember, some endpoints are wide-open and have no useful role control or access control.

Access control

Access control is accomplished by JWT tokens sent via the Authentication header with every API endpoint call. User role is encoded in the JWT body by object sub. For Local User, it's pointing to 'U', for Administrator to 'M' and for Remote pointing to KID of registered authenticator.
Local authentication
External authentication
{
"scope": "logger:get",
"sub": "U",
"iat": 1647871445,
"exp": 1647900245,
"jti": "1YU4YpnVy5rXauwxT2IXRX91hTCxaUEtGdOBK25zA40="
}
{
"scope": "keymgmt:list",
"sub": "Qq/EGdvacmNrN6JFWVXglQ==",
"iat": 1647871122,
"exp": 1647872020,
"jti": "koQ4YsCf3L4iTrl2py6g7t3jvV9pwwsIr6//F96OfYI="
}
The general roles are as follows:
  • a few endpoints are wide-open (access control relaxed),
  • most endpoints required strict access control based on access scope and user role, and finally,
  • some of them have implemented weak access control, and just need a valid JWT token.

Initial configuration init structure format

Initialization argument init is a slightly modified JWT token. The modification is as follows:
  • the header has a new object ecdh indicating the JWT hash secret is a result of the ECDH algorithm, here x25519 (curve25519);
  • the arguments to the ECDH are in a body part, those are the iss (issuer or sender) and the aud (audience or receiver) objects
  • the signature is indicated by the alg (here HS256 a'ka SHA256) where the secret is a result of ECDH(iss_privatekey, aud)(issuer private is confidential, in the body public key part is sent, the aud is just a public key part - receiver can be validated, if she is a legitimated receiver
# header
{
"ecdh": "x25519",
"alg": "HS256",
"typ": "JWT"
}
# body
{
"jti": "OxNDYouIDLnetwcekFRLHcU5AzwC0Al9Jj1JiNgAuMA=",
"aud": "dMYaJwVrA/1gKj5syUyhsyerdfUT6LuoptmvKVs0oVc=",
"exp": 1648563063,
"iat": 1648563000,
"iss": "WK81qE4LsYBlEuXyutOm6d9DsgYUbGz6BEOIEoNrQio=",
"cfg": {
"masterkey": "WK81qE4LsYBlEuXyutOm6d9DsgYUbGz6BEOIEoNrQio=",
"userkey": "jJg5kI4ZMMWV7eG6GA1du0uJWi0SezS1cZfUgCP6r0Q=",
"user": "John Doe",
"email": "",
"hostname": "my.ence.do",
"ip": "192.168.7.1/24",
"storage_mode": 81,
"storage_disk0size": 8388608,
"dnsd": true,
"trusted_ts": true,
"trusted_backend": true,
"allow_keysearch": true,
"origin": "*"
}
}
# signature
<base64 encoded SHA256 hash>
A few comments are needed here:
  • the object inside the cfg object are common with the Configuration endpoint (the same names, meanings, and allowed values);
  • the masterkey object, like the userkey object is an Administrator public key (curve25519),
  • objects: jti, aud, exp are the same and were returned by Phase1 of the Initialization process (spk => aud);
  • the iss object is a duplication of the masterkey object (a requirement of the implemented modified version of JWT as commented above);
  • the whole JWT token is signed (HS256) where the secret is a result of ECDH between the aud (public key) and the masterkey private key.

Events and logs

Encedo HEM has implemented an advanced logging mechanism. Every security-related event are been logged. This includes failed access control, all key management operations and all operations of keys and secrets. The log file itself has built-in security measures against tampering or integrity violation.

Events type:

Event name & value
Description
LOG_TYPE_KEY_INIT (0)
First entry with log unique key.
LOG_TYPE_STARTUP (1)
Indicating successful device startup.
LOG_TYPE_REBOOT (2)
Reboot performed.
LOG_TYPE_SHUTDOWN (3)
Shutdown performed.
LOG_TYPE_UPGRADE (4)
Upgrade (FW or UI) performed.
LOG_TYPE_TRNG_FAILED (5)
TRNG entropy test failed.
LOG_TYPE_TLS_ERROR (6)
TLS1.3 initialization failed.
LOG_TYPE_SELFTEST_PASSED (7)
Self-Test was successful.
LOG_TYPE_NON_SECURE_STATE (8)
Entered into the fail state.
LOG_TYPE_LOGGER_LIST_LOG (9)
Log listed.
LOG_TYPE_LOGGER_DELETE_LOG (10)
Log file deleted (not implemented).
LOG_TYPE_LOGGER_READ_LOG (11)
Log file read.
LOG_TYPE_FAILED_SCOPE_CHECK (12)
Access scope check failed.
LOG_TYPE_AUTH_SUCCESS_INTERNAL (13)
JWT access token issued for User or Administrator.
LOG_TYPE_AUTH_SUCCESS_EXTERNAL (14)
JWT access token issued for the external authenticator.
LOG_TYPE_AUTH_PAIRED_EXTERNAL (15)
Successfully registered an external authenticator.
LOG_TYPE_CONFIG_UPDATED (18)
Device configuration updated.
LOG_TYPE_RTC_SET (19)
RTC (time&date) updated.
LOG_TYPE_KEY_GENERATION (20)
New key generated.
LOG_TYPE_KEY_DELETE (21)
Key deleted.

Events results:

Result name & value
Description
LOG_RESULT_OK (0)
All went well
LOG_RESULT_FAILED (1)
Execution failed
LOG_RESULT_ERROR (2)
Cannot execute - e.g. parameters error

Response codes

This is a list of all possible API response codes and their meaning:
Code
Description
200
Operation successful - all done. The opposite is code 406.
201
Created - background task has been created and is running.
202
Accepted - background task still ongoing, retry later.
400
Incorrect argument(s) - a general input data validation failed, including JSON parsing.
401
Missing or invalid JWT TOKEN - the token presented is invalid (signature), expired or is malformated
403
Incorrect access scope - the access control validation failed. This error issue an audit log write of a source and result of the error.
404
Not found - the operation path (endpoint) does not exist.
406
Operation failed - operation due to the errors, malformed or out-of-range data cannot succeed.
409
Incorrect internal state - the operation cannot be completed due to the incorrect internal state: fails state, the disk is busy, ongoing upgrade etc.
411
Protocol error - POST requests require a Content-Length header.
412
Protocol error - CORS validation failed.
413
Protocol error - POST request body too big (too long).
418
TLS (HTTPS) connection required - the operation endpoint required a trusted channel aka encrypted TLS connection.
500
Internal Server error - very rare error, most a case critical. Can be raised by an endpoint anytime.

Examples

Let's make it straight - you need working examples, right?.
Enjoy :)