Coverage Report

Created: 2025-02-15 06:25

/src/wireshark/wsutil/curve25519.c
Line
Count
Source (jump to first uncovered line)
1
/* curve25519.c
2
 * NaCl/Sodium-compatible API for Curve25519 cryptography.
3
 *
4
 * Copyright (c) 2018, Peter Wu <peter@lekensteyn.nl>
5
 *
6
 * Wireshark - Network traffic analyzer
7
 * By Gerald Combs <gerald@wireshark.org>
8
 * Copyright 1998 Gerald Combs
9
 *
10
 * SPDX-License-Identifier: GPL-2.0-or-later
11
 */
12
13
#include "curve25519.h"
14
#include <gcrypt.h>
15
16
static inline void
17
copy_and_reverse(unsigned char *dest, const unsigned char *src, size_t n)
18
0
{
19
0
    for (size_t i = 0; i < n; i++) {
20
0
        dest[n - 1 - i] = src[i];
21
0
    }
22
0
}
23
24
static int
25
x25519_mpi(unsigned char *q, const unsigned char *n, gcry_mpi_t mpi_p)
26
0
{
27
0
    unsigned char priv_be[32];
28
0
    unsigned char result_be[32];
29
0
    size_t result_len = 0;
30
0
    gcry_mpi_t mpi = NULL;
31
0
    gcry_ctx_t ctx = NULL;
32
0
    gcry_mpi_point_t P = NULL;
33
0
    gcry_mpi_point_t Q = NULL;
34
0
    int r = -1;
35
36
    /* Default to infinity (all zeroes). */
37
0
    memset(q, 0, 32);
38
39
    /* Keys are in little-endian, but gcry_mpi_scan expects big endian. Convert
40
     * keys and ensure that the result is a valid Curve25519 secret scalar. */
41
0
    copy_and_reverse(priv_be, n, 32);
42
0
    priv_be[0] &= 127;
43
0
    priv_be[0] |= 64;
44
0
    priv_be[31] &= 248;
45
0
    gcry_mpi_scan(&mpi, GCRYMPI_FMT_USG, priv_be, 32, NULL);
46
47
0
    if (gcry_mpi_ec_new(&ctx, NULL, "Curve25519")) {
48
        /* Should not happen, possibly out-of-memory. */
49
0
        goto leave;
50
0
    }
51
52
    /* Compute Q = nP */
53
0
    Q = gcry_mpi_point_new(0);
54
0
    P = gcry_mpi_point_set(NULL, mpi_p, NULL, GCRYMPI_CONST_ONE);
55
0
    gcry_mpi_ec_mul(Q, mpi, P, ctx);
56
57
    /* Note: mpi is reused to store the result. */
58
0
    if (gcry_mpi_ec_get_affine(mpi, NULL, Q, ctx)) {
59
        /* Infinity. */
60
0
        goto leave;
61
0
    }
62
63
0
    if (gcry_mpi_print(GCRYMPI_FMT_USG, result_be, 32, &result_len, mpi)) {
64
        /* Should not happen, possibly out-of-memory. */
65
0
        goto leave;
66
0
    }
67
0
    copy_and_reverse(q, result_be, result_len);
68
0
    r = 0;
69
70
0
leave:
71
0
    gcry_mpi_point_release(P);
72
0
    gcry_mpi_point_release(Q);
73
0
    gcry_ctx_release(ctx);
74
0
    gcry_mpi_release(mpi);
75
    /* XXX erase priv_be and result_be */
76
0
    return r;
77
0
}
78
79
int
80
crypto_scalarmult_curve25519(unsigned char *q, const unsigned char *n,
81
                             const unsigned char *p)
82
0
{
83
0
    unsigned char p_be[32];
84
0
    gcry_mpi_t mpi_p = NULL;
85
86
0
    copy_and_reverse(p_be, p, 32);
87
    /* Clear unused bit. */
88
0
    p_be[0] &= 0x7f;
89
0
    gcry_mpi_scan(&mpi_p, GCRYMPI_FMT_USG, p_be, 32, NULL);
90
0
    int r = x25519_mpi(q, n, mpi_p);
91
0
    gcry_mpi_release(mpi_p);
92
0
    return r;
93
0
}
94
95
int
96
crypto_scalarmult_curve25519_base(unsigned char *q, const unsigned char *n)
97
0
{
98
0
    gcry_mpi_t mpi_basepoint_x = gcry_mpi_set_ui(NULL, 9);
99
0
    int r = x25519_mpi(q, n, mpi_basepoint_x);
100
0
    gcry_mpi_release(mpi_basepoint_x);
101
0
    return r;
102
0
}