2 * Not original to the mbedtls library. Taken from
3 * https://github.com/mwarning/mbedtls_ecp_compression
4 * to solve mbedtls' lack of support for elliptic point
5 * compression and decompression
7 * Released under CC0 1.0 Universal License
11 * This is all about mbedtls_ecp_decompress() and mbedtls_ecp_compress()
13 * Perform X25519 / Curve25519 point compression and decompression for mbedtls.
14 * As of mbedtls 2.5.1, mbedtls does not support decompression yet.
18 #define MBEDTLS_ALLOW_PRIVATE_ACCESS
20 #include "ecc_point_compression.h"
22 int mbedtls_ecp_decompress(
23 const mbedtls_ecp_group
*grp
,
24 const unsigned char *input
, size_t ilen
,
25 unsigned char *output
, size_t *olen
, size_t osize
33 plen
= mbedtls_mpi_size(&grp
->P
);
38 return (MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
);
41 return (MBEDTLS_ERR_ECP_BAD_INPUT_DATA
);
43 if (input
[0] != 0x02 && input
[0] != 0x03)
44 return (MBEDTLS_ERR_ECP_BAD_INPUT_DATA
);
46 // output will consist of 0x04|X|Y
47 memcpy(output
, input
, ilen
);
55 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&x
, input
+ 1, plen
));
58 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&r
, &x
, &x
));
61 if (grp
->A
.p
== NULL
) {
62 // Special case where a is -3
63 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&r
, &r
, 3));
65 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&r
, &r
, &grp
->A
));
69 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&r
, &r
, &x
));
72 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&r
, &r
, &grp
->B
));
74 // Calculate square root of r over finite field P:
75 // r = sqrt(x^3 + ax + b) = (x^3 + ax + b) ^ ((P + 1) / 4) (mod P)
78 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&n
, &grp
->P
, 1));
81 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&n
, 2));
83 // r ^ ((P + 1) / 4) (mod p)
84 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&r
, &r
, &n
, &grp
->P
, NULL
));
86 // Select solution that has the correct "sign" (equals odd/even solution in finite group)
87 if ((input
[0] == 0x03) != mbedtls_mpi_get_bit(&r
, 0)) {
89 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&r
, &grp
->P
, &r
));
93 ret
= mbedtls_mpi_write_binary(&r
, output
+ 1 + plen
, plen
);
103 int mbedtls_ecp_compress(
104 const mbedtls_ecp_group
*grp
,
105 const unsigned char *input
, size_t ilen
,
106 unsigned char *output
, size_t *olen
, size_t osize
110 plen
= mbedtls_mpi_size(&grp
->P
);
115 return (MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
);
117 if (ilen
!= 2 * plen
+ 1)
118 return (MBEDTLS_ERR_ECP_BAD_INPUT_DATA
);
120 if (input
[0] != 0x04)
121 return (MBEDTLS_ERR_ECP_BAD_INPUT_DATA
);
123 // output will consist of 0x0?|X
124 memcpy(output
, input
, *olen
);
126 // Encode even/odd of Y into first byte (either 0x02 or 0x03)
127 output
[0] = 0x02 + (input
[2 * plen
] & 1);