6 ex__ecc_8c
gullradriel edited this page 2026-10-09 00:55:18 +02:00

examples/ex_ecc.c

Functions

Name
int main(void )

Attributes

Name
int failures

Functions Documentation

function main

int main(
    void 
)

Attributes Documentation

variable failures

static int failures = 0;

Source code

/*
 * Nilorea Library
 * Copyright (C) 2005-2026 Castagnier Mickael
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * permissions and limitations under the License.
 *
 * SPDX-License-Identifier: Apache-2.0
 */


#include "nilorea/n_ecc.h"
#include "nilorea/n_log.h"

#include <stdio.h>
#include <string.h>

static int failures = 0;

int main(void) {
    set_log_level(LOG_ERR);

#if !N_ECC_AVAILABLE
    /* Curve25519 needs OpenSSL 1.1.1. On the OpenSSL 1.0.2 this library still
       supports, every n_ecc entry point is a logged failure, so there is
       nothing here to exercise. Report the skip and succeed rather than count
       an absent primitive as a bug. */
    n_log(LOG_NOTICE, "ex_ecc: skipped, this OpenSSL does not provide X25519/Ed25519");
    return 0;
#else
    /* X25519: the two parties derive the same shared secret */
    unsigned char a_priv[N_ECC_KEY_LEN], a_pub[N_ECC_KEY_LEN];
    unsigned char b_priv[N_ECC_KEY_LEN], b_pub[N_ECC_KEY_LEN];
    unsigned char sh_a[N_ECC_KEY_LEN], sh_b[N_ECC_KEY_LEN];
    if (n_x25519_keypair(a_priv, a_pub) != 0 || n_x25519_keypair(b_priv, b_pub) != 0) {
        n_log(LOG_ERR, "x25519 keypair failed");
        failures++;
    } else if (n_x25519_derive(a_priv, b_pub, sh_a) != 0 || n_x25519_derive(b_priv, a_pub, sh_b) != 0) {
        n_log(LOG_ERR, "x25519 derive failed");
        failures++;
    } else if (memcmp(sh_a, sh_b, N_ECC_KEY_LEN) != 0) {
        n_log(LOG_ERR, "x25519 shared secrets differ");
        failures++;
    }
    /* two independent keypairs must not collide */
    if (memcmp(a_pub, b_pub, N_ECC_KEY_LEN) == 0) {
        n_log(LOG_ERR, "x25519 keypairs collided");
        failures++;
    }

    /* Ed25519: sign then verify; a tampered signature or message must not verify */
    unsigned char s_priv[N_ECC_KEY_LEN], s_pub[N_ECC_KEY_LEN];
    unsigned char sig[N_ECC_SIG_LEN];
    const unsigned char msg[] = "the quick brown fox";
    size_t mlen = sizeof(msg) - 1;
    if (n_ed25519_keypair(s_priv, s_pub) != 0) {
        n_log(LOG_ERR, "ed25519 keypair failed");
        failures++;
    } else if (n_ed25519_sign(s_priv, msg, mlen, sig) != 0) {
        n_log(LOG_ERR, "ed25519 sign failed");
        failures++;
    } else {
        if (n_ed25519_verify(s_pub, msg, mlen, sig) != 0) {
            n_log(LOG_ERR, "ed25519 verify (good) failed");
            failures++;
        }
        sig[0] ^= 0x01;
        if (n_ed25519_verify(s_pub, msg, mlen, sig) == 0) {
            n_log(LOG_ERR, "ed25519 verify accepted a tampered signature");
            failures++;
        }
        sig[0] ^= 0x01;
        unsigned char m2[sizeof(msg) - 1];
        memcpy(m2, msg, mlen);
        m2[0] ^= 0x01;
        if (n_ed25519_verify(s_pub, m2, mlen, sig) == 0) {
            n_log(LOG_ERR, "ed25519 verify accepted a tampered message");
            failures++;
        }
    }

    if (failures) {
        n_log(LOG_ERR, "ex_ecc: %d failure(s)", failures);
        return 1;
    }
    n_log(LOG_NOTICE, "ex_ecc: all checks passed");
    return 0;
#endif
}