X.509 Device Identity
These functions create and hold the device’s cryptographic identity: an elliptic-curve key pair (secp256r1) and a self-signed certificate, stored in a reserved flash region. They survive reboots and application downloads, and the private key never leaves the chip.
The identity is what lets a cloud platform authenticate the device without a shared secret — see MQTT / MQTTS.
Install the library first — see Library. Every text parameter is a POINTER TO BYTE, passed with ADR().
The library at a glance
Section titled “The library at a glance”| File | nXPicoX509.compiled-library — 598 KB |
| Type | Precompiled library: no source, nothing to build |
| Exported functions | 8, listed below |
| Boards | nXPico W and nXPico M |
| Requires | Nothing — the implementation is in the firmware; the library only declares it |
Installing the library does not add code to your application: it declares functions that the runtime already carries. That is why it works on two different boards with one file, and why a board whose firmware lacks those functions rejects the download instead of failing silently.
x509GenerateDeviceCert
Section titled “x509GenerateDeviceCert”Generates key and certificate. Asynchronous — returns immediately, the work takes about 450 ms.
FUNCTION x509GenerateDeviceCert : DINTVAR_INPUT pSubject : POINTER TO BYTE; (* e.g. ADR('CN=nxpico-01'); NULL = default *) diValidityDays : DINT; (* ignored: fixed validity 2025-2035 *) xForce : BOOL; (* TRUE = regenerate even if one exists *)END_VAR| Return | Meaning |
|---|---|
10 | accepted, generation started — the only value returned |
An invalid pSubject is reported later, as 2 in x509GetGenerateStatus().
diValidityDays is currently ignored: the certificate is always valid from 2025-01-01 to 2035-01-01.
Wait for completion with x509HasDeviceCert() or x509GetGenerateStatus(). Calling it again while generation is running is harmless — it returns 10. With xForce = FALSE and an identity already present it does nothing and the status becomes 0.
x509HasDeviceCert
Section titled “x509HasDeviceCert”FUNCTION x509HasDeviceCert : BOOLTRUE when a valid identity is in flash. The simplest way to know generation has finished.
x509GetGenerateStatus
Section titled “x509GetGenerateStatus”FUNCTION x509GetGenerateStatus : DINT| Return | Meaning |
|---|---|
10 | generation in progress |
0 | completed successfully |
2 | pSubject is not a valid pointer |
| other | error code |
x509GetDeviceCertLen
Section titled “x509GetDeviceCertLen”FUNCTION x509GetDeviceCertLen : DINTLength in bytes of the PEM certificate, 0 if absent. Typically 595.
x509DumpDeviceCert
Section titled “x509DumpDeviceCert”Prints the whole certificate to the diagnostic log, delimited and ready to copy. This is the recommended way to extract the certificate for registration on a cloud platform.
FUNCTION x509DumpDeviceCert : DINT| Return | Meaning |
|---|---|
10 | accepted, printing follows immediately |
1 | no certificate in flash — generate the identity first |
[X509] ---- inizio certificato device (595 byte): copiare da qui ---------BEGIN CERTIFICATE-----MIIB...-----END CERTIFICATE-----[X509] ---- fine certificato device ----Copy everything between the two delimiters, -----BEGIN and -----END lines included.
x509GetDeviceCert
Section titled “x509GetDeviceCert”Copies the PEM certificate into an application buffer.
FUNCTION x509GetDeviceCert : DINTVAR_INPUT pBuf : POINTER TO BYTE; udiSize : UDINT; (* use SIZEOF(yourBuffer) *)END_VAR| Return | Meaning |
|---|---|
0 | copied |
15 | buffer too small |
1 | no certificate in flash |
x509GetDeviceCertChunk
Section titled “x509GetDeviceCertChunk”Reads the certificate piecewise, to move it into small buffers or push it onto a socket.
FUNCTION x509GetDeviceCertChunk : DINTVAR_INPUT diOffset : DINT; (* from 0 upwards *) pBuf : POINTER TO BYTE; udiSize : UDINT;END_VARReturns the number of bytes copied, 0 when there is nothing left.
x509GenerateCsr
Section titled “x509GenerateCsr”Generates a Certificate Signing Request, to have the certificate signed by a CA.
FUNCTION x509GenerateCsr : DINTVAR_INPUT pSubject : POINTER TO BYTE; pBuf : POINTER TO BYTE; udiSize : UDINT;END_VARReturns 0 if the CSR was written to the buffer, 1 if the buffer is too small. Requires an identity to already exist (without one it also returns 1) — the CSR is signed with the device’s private key.
Complete example
Section titled “Complete example”VAR xGen, xGenPrev, xDump, xDumpPrev : BOOL; diRes, diStatus, diCertLen : DINT; xHasCert : BOOL;END_VAR(* generation: once in the life of the device *)IF xGen AND NOT xGenPrev THEN diRes := x509GenerateDeviceCert(ADR('CN=nxpico-01'), 3650, FALSE);END_IFxGenPrev := xGen;
xHasCert := x509HasDeviceCert();diStatus := x509GetGenerateStatus();diCertLen := x509GetDeviceCertLen();
(* print it to the log, to register it on the platform *)IF xDump AND NOT xDumpPrev THEN diRes := x509DumpDeviceCert();END_IFxDumpPrev := xDump;The log reports each phase:
[X509] fase 1/3: keygen EC secp256r1...[X509] fase 1/3 keygen -> 0 (219 ms)[X509] fase 2/3 cert -> 0 (224 ms)[X509] fase 3/3 save -> 0 (10 ms) has=1