facil.io

#P-384 (secp384r1)

c
#define FIO_P384
#include "fio-stl.h"

P-384 is the NIST secp384r1 curve. In this STL, it is a verifier: it checks ECDSA P-384 signatures, mainly for TLS 1.3 certificate chains and CA roots that use P-384.

There is no signing or key-generation API here. Just verification. Nice and focused.

Security note: this implementation has not been independently audited. It is meant for verification of public data; prefer a tested crypto library when certificate trust is central to your application.

#What It Provides

Use Function Notes
Verify DER signature fio_ecdsa_p384_verify Accepts SEQUENCE { r INTEGER, s INTEGER } and a 97-byte uncompressed public key.
Verify raw signature fio_ecdsa_p384_verify_raw Accepts raw 48-byte r, s, x, and y values.

Curve parameters from NIST FIPS 186-4:

  • p = 2^384 - 2^128 - 2^96 + 2^32 - 1
  • n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973
  • curve equation: y² = x³ - 3x + b (mod p)
  • coordinate size: 48 bytes

#Verification API

#fio_ecdsa_p384_verify

c
SFUNC int fio_ecdsa_p384_verify(const uint8_t *sig,
                                size_t sig_len,
                                const uint8_t *msg_hash,
                                const uint8_t *pubkey,
                                size_t pubkey_len);

Verifies a DER-encoded ECDSA P-384 signature over a 48-byte SHA-384 hash.

  • sig is a DER SEQUENCE { r INTEGER, s INTEGER }.
  • sig_len is the signature length in bytes.
  • msg_hash is the SHA-384 hash of the message, exactly 48 bytes.
  • pubkey must be an uncompressed public key: 0x04 || x || y.
  • pubkey_len must be 97.
  • Returns 0 for a valid signature, -1 for invalid input or a bad signature.

The function validates the public-key wrapper, decodes r and s from DER, then calls fio_ecdsa_p384_verify_raw.

Compressed public keys are not accepted by this API.

#fio_ecdsa_p384_verify_raw

c
SFUNC int fio_ecdsa_p384_verify_raw(const uint8_t r[48],
                                    const uint8_t s[48],
                                    const uint8_t msg_hash[48],
                                    const uint8_t pubkey_x[48],
                                    const uint8_t pubkey_y[48]);

Verifies an ECDSA P-384 signature when the signature and public key are already decoded.

All inputs are fixed-width big-endian values:

  • r and s: 48-byte signature scalars.
  • msg_hash: 48-byte SHA-384 hash.
  • pubkey_x and pubkey_y: 48-byte public-key coordinates.

The verifier checks that r and s are in range, checks the public point is on the P-384 curve, computes the ECDSA verification equation, and returns 0 only when r == R.x mod n.

#Example

c
#define FIO_P384
#include "fio-stl.h"

int verify_cert_sig(const uint8_t *sig,
                    size_t sig_len,
                    const uint8_t hash[48],
                    const uint8_t pubkey[97]) {
  if (fio_ecdsa_p384_verify(sig, sig_len, hash, pubkey, 97))
    return -1;
  return 0;
}

#Implementation Notes

The implementation uses 6 × 64-bit limbs for field elements, Jacobian coordinates for point work, P-384-specific modular reduction, and a double-scalar multiplication path for ECDSA verification.

The scalar multiplication is for public verification data. Do not treat this header as a P-384 signing toolkit; there is no public signing API, and private-key use should go to an audited library.