Commit graph

63 commits

Author SHA1 Message Date
Felipe Moura
ce645060fa crypto: add CRYPTO_AES_CTR_SSH variant (128-bit big-endian counter)
The existing CRYPTO_AES_CTR is the RFC 3686 profile: the last 4 bytes of
the key are a nonce, the IV is 8 bytes and only the low 32 bits of the
counter block are incremented. SSH aes128/192/256-ctr (RFC 4344) instead
uses the key as-is (no embedded nonce) and treats the whole 16-byte IV as
the initial counter block, incremented as a 128-bit big-endian integer,
with the first keystream block being E(IV).

Add CRYPTO_AES_CTR_SSH as a new enc_xform mirroring the CRYPTO_CHACHA20_DJB
addition. It reuses struct aes_ctr_ctx and the AES block; only setkey (full
key, no nonce), reinit (full 16-byte counter) and crypt (encrypt-then-
increment over all 16 bytes) differ from the RFC 3686 variant.

Keystream validated against `openssl enc -aes-128-ctr`, including a counter
that carries across byte boundaries and a non-block-aligned tail.

Signed-off-by: Felipe Moura <moura.fmo@gmail.com>
2026-07-16 15:42:10 +08:00
Felipe Moura
5e2ce6190d crypto: add CRYPTO_CHACHA20_DJB variant (64-bit counter/nonce)
CRYPTO_CHACHA20 implements the RFC 8439/IETF parameterization (32-bit
counter + 96-bit nonce). SSH's chacha20-poly1305@openssh.com uses the
original DJB construction instead: a 64-bit block counter in state
words 12..13 and a 64-bit nonce in words 14..15 (libtomcrypt's
chacha_ivctr64). The two layouts produce different keystreams for the
same key, so an SSH server cannot interoperate with OpenSSH clients
through the IETF variant.

Signed-off-by: Felipe Moura <moura.fmo@gmail.com>
2026-07-11 17:58:55 -03:00
makejian
bdd68ed1e5 crypto: Add ChaCha20/ChaCha20-Poly1305 to /dev/crypto, fix RFC 8439 nonce.
Expose the ChaCha20 stream cipher and the ChaCha20-Poly1305 AEAD through
the OCF crypto framework (/dev/crypto) so applications such as an SSH
server (chacha20-poly1305) can use them directly, and fix the underlying
ChaCha nonce/counter layout so both match RFC 8439.

RFC 8439 nonce layout fix
-------------------------
chacha_ivsetup() previously used the original DJB layout: a 64-bit block
counter (input[12..13]) followed by a 64-bit nonce (input[14..15]). RFC
8439 defines a 32-bit block counter (input[12]) and a 96-bit / 12-byte
nonce (input[13..15]). With the old layout the existing ChaCha20-Poly1305
AEAD could not reproduce the RFC 8439 test vectors (the last 4 bytes of a
12-byte nonce were consumed as the high half of the counter). This
commit switches chacha_ivsetup() to the RFC 8439 layout and updates the
ChaCha20-Poly1305 one-shot helpers to pass a 12-byte nonce accordingly.

Standalone ChaCha20 on the unified enc path
-------------------------------------------
Instead of introducing a separate multi-buffer stream path (parallel
encrypt_multi/decrypt_multi callbacks), extend the existing enc_xform
encrypt/decrypt callback signature with a length argument:

  void (*encrypt)(caddr_t, FAR uint8_t *, size_t len);
  void (*decrypt)(caddr_t, FAR uint8_t *, size_t len);

With that single change every cipher, block or stream, flows through the
same swcr_encdec path. swcr_encdec already handles a short final block
via buflen = MIN(i, blocksize), so arbitrary-length data works without a
second code path. This is exactly how the existing stream ciphers
(AES-CTR/OFB/CFB) already behave: the cipher keeps its own counter in the
context and swcr_encdec feeds it whole blocks (only the last one may be
shorter). chacha20_crypt likewise relies on the underlying chacha state
block counter (input[12]) to continue the keystream across calls, so no
per-call keystream caching is needed.

  * chacha_private.h: chacha_ivsetup uses a 4-byte counter and a 12-byte
    nonce (RFC 8439).
  * chachapoly.c / chachapoly.h: split reinit into chacha20_reinit (raw,
    counter 0) and chachapoly_reinit (AEAD, counter 1); chacha20_crypt
    takes a length and encrypts it in one pass, mirroring aes_ctr_crypt;
    12-byte nonce for the one-shot AEAD helpers.
  * xform.h / xform.c: add size_t len to encrypt/decrypt; add
    enc_xform_chacha20 (blocksize 64, 12-byte IV).
  * cryptodev.c / cryptosoft.c: register CRYPTO_CHACHA20 as a txform
    cipher, route new sessions to enc_xform_chacha20, feed the AEAD AAD
    through crp_aad/crp_aadlen, and handle the short final block in
    swcr_encdec.
  * cryptodev.h: add CRYPTO_CHACHA20; bump EALG_MAX_BLOCK_LEN to 64.

This keeps all ciphers on one uniform path instead of maintaining two,
and any future stream cipher drops in with just an xform table entry.

Impact: extends an internal kernel callback signature (enc_xform
encrypt/decrypt). All in-tree implementations are updated in the same
commit and the user-facing /dev/crypto ABI is unchanged, so this is
self-contained and not a breaking change for existing configurations.

Testing:
  Build host: Ubuntu Linux x86_64, GCC (host sim toolchain)
  Target: sim:crypto (CONFIG_ARCH=sim)
  Ran the crypto test apps. ChaCha20 uses RFC 8439 2.4.2 vectors
  (including a 375-byte multi-block vector exercising cross-block counter
  continuity); ChaCha20-Poly1305 uses the RFC 8439 2.8.2 AEAD vector.
  A full regression of the other ciphers was run to confirm the extended
  encrypt/decrypt signature does not change their behaviour:

    nsh> chacha20
    chacha20: 2/2 vectors passed
    nsh> chachapoly
    OK test vector 0
    chachapoly: 1/1 vectors passed
    nsh> des3cbc          -> all vectors OK
    nsh> aescbc           -> all vectors OK
    nsh> aesctr           -> all vectors OK
    nsh> aesxts           -> 14 vectors OK (encrypt + decrypt)
    nsh> hmac             -> md5 / sha1 / sha256 all success

Signed-off-by: makejian <makejian@xiaomi.com>
2026-07-11 10:19:39 -03:00
Peter Barada
fb428899dc crypto: Support SHA2_224_HMAC
Since already have support for SHA2-224, extend cryptodev/cryptosoft
to support HMAC version of SHA2-224.

Signed-off-by: Peter Barada <peter.barada@gmail.com>
2026-07-04 14:15:17 +08:00
Vlad Pruteanu
3039184806 crypto/cryptosoft: Add support for PBKDF2
This adds support for PBKDF2 (SHA1 and SHA256) while leveraging
the existing infrastructure for HMAC.

Signed-off-by: Vlad Pruteanu <pruteanuvlad1611@yahoo.com>
2026-03-29 17:23:03 -03:00
makejian
c8145313ae crypto: support software key management based on MTD
This patch adds support for managing cryptographic keys using MTD storage.

It enables the persistence of keys across reboots using a software-based key management system.

Includes fixes for compilation warnings and validation logic.

Signed-off-by: makejian <makejian@xiaomi.com>
2026-01-28 11:52:12 +08:00
makejian
3b151ae44b crypto/cryptodev: fix async callback
Fix incorrect memory management for asynchronous process callbacks.

Ensure callback memory is self-managed to prevent leaks or use-after-free issues.

Signed-off-by: makejian <makejian@xiaomi.com>
2026-01-27 19:30:14 +08:00
makejian
2878fa3c38 crypto: export rsa with pkcs1.5 and pss mode
Add support for exporting RSA operations with PKCS#1 v1.5 and PSS padding schemes through the cryptodev interface.

This enables both traditional and modern RSA signature schemes:
- CRK_RSA_PKCS15_SIGN/VERIFY for PKCS#1 v1.5 padding
- CRK_RSA_PSS_SIGN/VERIFY for PSS padding

Signed-off-by: makejian <makejian@xiaomi.com>
2026-01-27 19:30:14 +08:00
makejian
85ba80a90e crypto/ecc: add SPDX license identifier
Add BSD-2-Clause SPDX license identifier to ECC source and header files.

Signed-off-by: makejian <makejian@xiaomi.com>
2026-01-26 10:55:57 +08:00
makejian
be2e72dac2 crypto/ecc: supports exporting generated keys in uncompressed form
Export public keys as separate X and Y coordinates for uncompressed format.

Signed-off-by: makejian <makejian@xiaomi.com>
2026-01-26 10:55:57 +08:00
makejian
3f0cc5f09c crypto: export algorithm about ecc
Transplanting the ECC algorithm from https://github.com/jestan/easy-ecc

which is BSD lisence

Signed-off-by: makejian <makejian@xiaomi.com>
2026-01-26 10:55:57 +08:00
makejian
5b52a32f5a crypto/crypto.c: Determine the order of obtained crypto drivers
After adding the cross-core crypto driver, there are now three encryption modes:
1. Hardware driver in local core
2. Crypto driver in remote core
3. Software encryption in local core

This prioritizes local hardware driver first, then remote driver (typically hardware),
and finally local software encryption as a fallback.

Signed-off-by: makejian <makejian@xiaomi.com>
2026-01-21 00:25:07 +08:00
makejian
e23dd613c9 crypto/cryptodev: optimize without dynamic memory in crypto process
Replace dynamic memory allocation with stack-based variables in cryptodev_op().
This eliminates kmm_malloc/kmm_free overhead and simplifies error handling
by removing the need for goto bail cleanup paths.

Signed-off-by: makejian <makejian@xiaomi.com>
2026-01-21 00:25:07 +08:00
makejian
66f9329839 crypto/cryptodev: export ivlen to support different cipher algs
Add ivlen field to crypt_op and crp_ivlen to cryptop structure to support
cipher algorithms with different IV lengths.

Signed-off-by: makejian <makejian@xiaomi.com>
2026-01-21 00:25:07 +08:00
makejian
143547128b crypto/cryptodev: add encrypt op and olen for support virtio mode
Add olen field to crypt_op structure and crp_olen to cryptop structure
to support output length tracking in virtio crypto mode.

Signed-off-by: makejian <makejian@xiaomi.com>
2026-01-21 00:25:07 +08:00
makejian
cdfe81ff4c crypto/siphash: avoid redefine name issue
Rename siphash related symbols to avoid conflicts with compiler-generated
section names. Tricore-gcc produces function sections with '_end' suffix,
which conflicts with siphash_end symbol.

Signed-off-by: makejian <makejian@xiaomi.com>
2026-01-19 23:25:37 +08:00
makejian
d15081838b crypto/cryptodev: support private data in driver
Add support for storing driver-specific private data in the crypto
driver structure. This allows crypto drivers to maintain session
state and other driver-specific information.

Signed-off-by: makejian <makejian@xiaomi.com>
2026-01-19 14:17:38 +08:00
makejian
b11901ffaf crypto: add key management and RSA/ECDSA keypair generation
Add key management interfaces and support for generating key pairs in RSA and ECDSA cryptographic processes to the cryptodev module.

Signed-off-by: makejian <makejian@xiaomi.com>
2026-01-17 11:41:23 +08:00
makejian
539c8f4ab2 crypto: add support for AES-CBC with 192/256-bit key sizes
Extend AES-CBC algorithm support to include 192-bit and 256-bit key sizes in addition to the existing 128-bit support. This enables broader compatibility with cryptographic standards and provides applications with additional key length options for enhanced security requirements.

Signed-off-by: makejian <makejian@xiaomi.com>
2026-01-15 16:11:19 -03:00
Alin Jerpelea
4a069358b6 LICENSE: update NuttX-PublicDomain SPDX identifier
According to the feedback from SPDX community we should use
LicenseRef-NuttX-PublicDomain because NuttX-PublicDomain
is not a valid SPDX id, so it will fail tests for SPDX spec compliance.

Signed-off-by: Alin Jerpelea <alin.jerpelea@sony.com>
2025-12-26 19:46:12 +08:00
Niccolò Maggioni
83dd57a488 crypto/hmac: Fix typo in function implementation names
"hmac" was mistyped as "hmca", breaking linking to some prototype
functions. Also, a couple of includes were missing.

Signed-off-by: Niccolò Maggioni <nicco.maggioni+nuttx@gmail.com>
2025-08-13 23:11:02 +08:00
Lars Kruse
3ce85ca54e style: fix spelling in code comments and strings 2025-05-23 10:48:41 +08:00
Alin Jerpelea
fe90b2ee7a include: migrate to SPDX identifier
Most tools used for compliance and SBOM generation use SPDX identifiers
This change brings us a step closer to an easy SBOM generation.

Signed-off-by: Alin Jerpelea <alin.jerpelea@sony.com>
2024-12-18 17:51:57 +08:00
Alin Jerpelea
6c322d0bfa include/crypto/sha1: migrate to SPDX identifier
Most tools used for compliance and SBOM generation use SPDX identifiers
This change brings us a step closer to an easy SBOM generation.

define NuttX local NuttX-PublicDomain identifier

 “Public Domain” is a concept distinct from copyright licensing;
it generally means that the work no longer has any copyright protection
or ownership, and therefore requires no license permission in order to
use, copy, modify, distribute, perform, display, etc.
In the United States – and many jurisdictions – copyright protections
attach automatically to creative works upon creation if they satisfy
certain minimum criteria.
“Public Domain” would thus represent a significant change to the legal
status of the work.
The rules around “Public Domain” often vary or are unspecified
jurisdiction to jurisdiction. Adding to the confusion, some
jurisdictions may not even recognize the concept of “Public Domain”
(or similar). As such, a license may nevertheless be required or implied
in these cases. Even in the U.S., there is no clear,
officially-sanctioned procedure for affirmatively placing
copyright-eligible works into the “Public Domain” aside from natural
statutory expiration of copyright. The bottom-line is, there are few if
any objective, brightline rules for proactively placing
copyright-eligible works into the Public Domain that we can broadly
rely on.

Signed-off-by: Alin Jerpelea <alin.jerpelea@sony.com>
2024-12-16 14:18:35 +08:00
Alin Jerpelea
3b1a5ccffa include/crypto/rijndael: migrate to SPDX identifier
Most tools used for compliance and SBOM generation use SPDX identifiers
This change brings us a step closer to an easy SBOM generation.

define NuttX local NuttX-PublicDomain identifier

 “Public Domain” is a concept distinct from copyright licensing;
it generally means that the work no longer has any copyright protection
or ownership, and therefore requires no license permission in order to
use, copy, modify, distribute, perform, display, etc.
In the United States – and many jurisdictions – copyright protections
attach automatically to creative works upon creation if they satisfy
certain minimum criteria.
“Public Domain” would thus represent a significant change to the legal
status of the work.
The rules around “Public Domain” often vary or are unspecified
jurisdiction to jurisdiction. Adding to the confusion, some
jurisdictions may not even recognize the concept of “Public Domain”
(or similar). As such, a license may nevertheless be required or implied
in these cases. Even in the U.S., there is no clear,
officially-sanctioned procedure for affirmatively placing
copyright-eligible works into the “Public Domain” aside from natural
statutory expiration of copyright. The bottom-line is, there are few if
any objective, brightline rules for proactively placing
copyright-eligible works into the Public Domain that we can broadly
rely on.

Signed-off-by: Alin Jerpelea <alin.jerpelea@sony.com>
2024-12-16 14:18:35 +08:00
Alin Jerpelea
a273b094fa include/crypto/poly1305: migrate to SPDX identifier
Most tools used for compliance and SBOM generation use SPDX identifiers
This change brings us a step closer to an easy SBOM generation.

define NuttX local NuttX-PublicDomain identifier

 “Public Domain” is a concept distinct from copyright licensing;
it generally means that the work no longer has any copyright protection
or ownership, and therefore requires no license permission in order to
use, copy, modify, distribute, perform, display, etc.
In the United States – and many jurisdictions – copyright protections
attach automatically to creative works upon creation if they satisfy
certain minimum criteria.
“Public Domain” would thus represent a significant change to the legal
status of the work.
The rules around “Public Domain” often vary or are unspecified
jurisdiction to jurisdiction. Adding to the confusion, some
jurisdictions may not even recognize the concept of “Public Domain”
(or similar). As such, a license may nevertheless be required or implied
in these cases. Even in the U.S., there is no clear,
officially-sanctioned procedure for affirmatively placing
copyright-eligible works into the “Public Domain” aside from natural
statutory expiration of copyright. The bottom-line is, there are few if
any objective, brightline rules for proactively placing
copyright-eligible works into the Public Domain that we can broadly
rely on.

Signed-off-by: Alin Jerpelea <alin.jerpelea@sony.com>
2024-12-16 14:18:35 +08:00
Alin Jerpelea
7e74a0b8fa include/crypto/md5: migrate to SPDX identifier
Most tools used for compliance and SBOM generation use SPDX identifiers
This change brings us a step closer to an easy SBOM generation.

define NuttX local NuttX-PublicDomain identifier

 “Public Domain” is a concept distinct from copyright licensing;
it generally means that the work no longer has any copyright protection
or ownership, and therefore requires no license permission in order to
use, copy, modify, distribute, perform, display, etc.
In the United States – and many jurisdictions – copyright protections
attach automatically to creative works upon creation if they satisfy
certain minimum criteria.
“Public Domain” would thus represent a significant change to the legal
status of the work.
The rules around “Public Domain” often vary or are unspecified
jurisdiction to jurisdiction. Adding to the confusion, some
jurisdictions may not even recognize the concept of “Public Domain”
(or similar). As such, a license may nevertheless be required or implied
in these cases. Even in the U.S., there is no clear,
officially-sanctioned procedure for affirmatively placing
copyright-eligible works into the “Public Domain” aside from natural
statutory expiration of copyright. The bottom-line is, there are few if
any objective, brightline rules for proactively placing
copyright-eligible works into the Public Domain that we can broadly
rely on.

Signed-off-by: Alin Jerpelea <alin.jerpelea@sony.com>
2024-12-16 14:18:35 +08:00
Alin Jerpelea
085c7e7b81 include/crypto/cast: migrate to SPDX identifier
Most tools used for compliance and SBOM generation use SPDX identifiers
This change brings us a step closer to an easy SBOM generation.

define NuttX local NuttX-PublicDomain identifier

 “Public Domain” is a concept distinct from copyright licensing;
it generally means that the work no longer has any copyright protection
or ownership, and therefore requires no license permission in order to
use, copy, modify, distribute, perform, display, etc.
In the United States – and many jurisdictions – copyright protections
attach automatically to creative works upon creation if they satisfy
certain minimum criteria.
“Public Domain” would thus represent a significant change to the legal
status of the work.
The rules around “Public Domain” often vary or are unspecified
jurisdiction to jurisdiction. Adding to the confusion, some
jurisdictions may not even recognize the concept of “Public Domain”
(or similar). As such, a license may nevertheless be required or implied
in these cases. Even in the U.S., there is no clear,
officially-sanctioned procedure for affirmatively placing
copyright-eligible works into the “Public Domain” aside from natural
statutory expiration of copyright. The bottom-line is, there are few if
any objective, brightline rules for proactively placing
copyright-eligible works into the Public Domain that we can broadly
rely on.

Signed-off-by: Alin Jerpelea <alin.jerpelea@sony.com>
2024-12-16 14:18:35 +08:00
Alin Jerpelea
cd2fcf5252 include: migrate to SPDX identifier
Most tools used for compliance and SBOM generation use SPDX identifiers
This change brings us a step closer to an easy SBOM generation.

Signed-off-by: Alin Jerpelea <alin.jerpelea@sony.com>
2024-10-04 08:18:42 +08:00
makejian
5b1d910ec6 nuttx/crypto: export asynchronous calling process
Signed-off-by: makejian <makejian@xiaomi.com>
2024-09-28 13:05:28 +08:00
makejian
bcb90fab7c nuttx/crypto: export Diffie-Hellman algorithm
Supplementary CRK_DH_MAKE_PUBLIC and CRK_DH_COMPUTE_KEY with curve25519
Signed-off-by: makejian <makejian@xiaomi.com>
2024-09-09 23:55:33 +08:00
makejian
882c09abb3 nuttx/crypto: export ecdsa sign and verify in SECP256R1 curve
Signed-off-by: makejian <makejian@xiaomi.com>
2024-09-09 23:55:33 +08:00
makejian
8de247543f crypto: export interfaces abort aes-cmac
Signed-off-by: makejian <makejian@xiaomi.com>
2024-08-27 07:44:06 -04:00
makejian
28974b8a21 crypto: export crc32 from /dev/crypto
Signed-off-by: makejian <makejian@xiaomi.com>
2024-08-27 07:44:06 -04:00
Petro Karashchenko
d499ac9d58 nuttx: fix multiple 'FAR', 'CODE' and style issues
Signed-off-by: Petro Karashchenko <petro.karashchenko@gmail.com>
2024-08-25 19:22:15 +08:00
makejian
10168903cc crypto/bn: add method to calculate inv mod and gcd
Signed-off-by: makejian <makejian@xiaomi.com>
2024-08-24 11:20:17 +08:00
makejian
21514e266a crypto/bn: bignum supports negative number operations
1.Add sign to indicate negative and positive
2.Fix case where there are negative numbers in the operation
3.expand to 512 bytes to support rsa2048

Signed-off-by: makejian <makejian@xiaomi.com>
2024-08-24 11:20:17 +08:00
makejian
9769816385 crypto: fix wrong implementation in crypto module
(1) RSA_PKCS15_VERIFY Misspell
(2) if iv not provided during decryption, iv should get from data.
It was not discovered before because all symmetric decryption comes with iv.
Signed-off-by: makejian <makejian@xiaomi.com>
2024-08-23 12:57:37 -03:00
makejian
947b24c8c1 crypto/poly1305: export poly1305 mac algorithm via /dev/crypto
Signed-off-by: makejian <makejian@xiaomi.com>
2024-08-22 13:40:24 +08:00
makejian
8628cc9c0e crypto/ripemd160: export ripemd160 algorithm via /dev/crypto
Signed-off-by: makejian <makejian@xiaomi.com>
2024-08-22 13:40:24 +08:00
makejian
ee6fdb2c85 crypto: import the ability to clone session
Signed-off-by: makejian <makejian@xiaomi.com>
2024-08-21 18:02:54 +08:00
raiden00pl
3ce9e34ec9 include/crypto/curve25519.h: fix gcc14 error
/home/raiden00/git/RTOS/nuttx/nuttx/include/crypto/curve25519.h:42:5: error: implicit declaration of function 'arc4random_buf' [-Wimplicit-function-declaration]
   42 |     arc4random_buf(secret, CURVE25519_KEY_SIZE);
2024-05-31 18:14:11 -03:00
makejian
3dbe2d790e crypto/rsa_verify: export rsa verify via /dev/crypto
kernel supports asymmetric encryption RSA signature verification
Signed-off-by: makejian <makejian@xiaomi.com>
2023-10-18 12:23:13 +08:00
makejian
aeac109e50 crypto/bn:Add exponentiation algorithm in bignum
add exponentiation algorithm: pow_mod_faster
Signed-off-by: makejian <makejian@xiaomi.com>
2023-10-18 12:23:13 +08:00
makejian
12935f2d33 crypto/bn: porting tiny-Bignum-C into nuttx crypto
porting from https://github.com/kokke/tiny-bignum-c commit ac136565378c624365e0f5f556d386b3966bff32 and adapting to the nuttx
Signed-off-by: makejian <makejian@xiaomi.com>
2023-10-18 12:23:13 +08:00
makejian
cb3abc48d7 crypto/cryptodev: expansion hash operation
(1) remove size restriction for single hash operation
(2) support hash operation to update uint32_t data
Signed-off-by: makejian <makejian@xiaomi.com>
2023-09-24 03:49:33 +08:00
makejian
f4f2c9ed49 crypto: fix multiple definition of `poly1305_init'
apps/crypto/libtomcrypt/libtomcrypt/src/mac/poly1305/poly1305.c:90: multiple definition of `poly1305_init';
nuttx/crypto/poly1305.c:51: first defined here
Signed-off-by: makejian <makejian@xiaomi.com>
2023-09-07 17:02:08 -03:00
makejian
afbe6239ae crypto: update aes algorithm process
(1)update iv in each encryption process
(2)support aes-ofb/aes-cfb128/aes-cfb8
Signed-off-by: makejian <makejian@xiaomi.com>
2023-08-21 13:05:19 +08:00
makejian
120aaf27b3 crypto: remove software algorithm coupling in cryptodev
Signed-off-by: makejian <makejian@xiaomi.com>
2023-08-17 13:12:36 +08:00
makejian
ac76a8fe0f crypto: export SHA224/SHA384 via /dev/crypto
(1)add sha224 algorithm in sha2.c
(2)export sha224/sha384
Signed-off-by: makejian <makejian@xiaomi.com>
2023-08-10 13:36:19 +08:00