/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 | } |