1 /*
2  * Copyright (c) 2024, The TrustedFirmware-M Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 
9 #include "cc3xx_ecdh.h"
10 
11 #include "cc3xx_ec.h"
12 #include "cc3xx_config.h"
13 
14 #include <stdint.h>
15 #include <stddef.h>
16 
17 #ifdef CC3XX_CONFIG_ECDH_ENABLE
cc3xx_lowlevel_ecdh(cc3xx_ec_curve_id_t curve_id,const uint32_t * private_key,size_t private_key_len,const uint32_t * public_key_x,size_t public_key_x_len,const uint32_t * public_key_y,size_t public_key_y_len,uint32_t * shared_secret,size_t shared_secret_len,size_t * shared_secret_size)18 cc3xx_err_t cc3xx_lowlevel_ecdh(cc3xx_ec_curve_id_t curve_id,
19                                 const uint32_t *private_key, size_t private_key_len,
20                                 const uint32_t *public_key_x, size_t public_key_x_len,
21                                 const uint32_t *public_key_y, size_t public_key_y_len,
22                                 uint32_t *shared_secret, size_t shared_secret_len,
23                                 size_t *shared_secret_size)
24 {
25     cc3xx_ec_curve_t curve;
26     cc3xx_pka_reg_id_t private_key_reg;
27     cc3xx_ec_point_affine shared_key_point, public_key_point;
28     cc3xx_err_t err;
29 
30     /* This sets up various curve parameters into PKA registers */
31     err = cc3xx_lowlevel_ec_init(curve_id, &curve);
32     if (err != CC3XX_ERR_SUCCESS) {
33         goto out;
34     }
35 
36     if (private_key_len > curve.modulus_size) {
37         err = CC3XX_ERR_ECDSA_INVALID_KEY;
38         goto out;
39     }
40 
41     if (public_key_x_len > curve.modulus_size) {
42         err = CC3XX_ERR_ECDSA_INVALID_KEY;
43         goto out;
44     }
45 
46     if (public_key_y_len > curve.modulus_size) {
47         err = CC3XX_ERR_ECDSA_INVALID_KEY;
48         goto out;
49     }
50 
51     if (shared_secret_len < curve.modulus_size) {
52         err = CC3XX_ERR_BUFFER_OVERFLOW;
53         goto out;
54     }
55 
56     shared_key_point = cc3xx_lowlevel_ec_allocate_point();
57     public_key_point = cc3xx_lowlevel_ec_allocate_point();
58     private_key_reg = cc3xx_lowlevel_pka_allocate_reg();
59 
60     cc3xx_lowlevel_pka_write_reg_swap_endian(private_key_reg, private_key, private_key_len);
61     cc3xx_lowlevel_pka_write_reg_swap_endian(public_key_point.x, public_key_x, curve.modulus_size);
62     cc3xx_lowlevel_pka_write_reg_swap_endian(public_key_point.y, public_key_y, curve.modulus_size);
63 
64     err = cc3xx_lowlevel_ec_multipy_point_by_scalar(&curve, &public_key_point, private_key_reg,
65                                            &shared_key_point);
66 
67     /* SEC1 paragraph 3.3.1: Output the x coordinate only as the shared secret */
68     cc3xx_lowlevel_pka_read_reg_swap_endian(shared_key_point.x, shared_secret, curve.modulus_size);
69     *shared_secret_size = curve.modulus_size;
70 
71 out:
72     cc3xx_lowlevel_ec_uninit();
73 
74     return err;
75 }
76 #endif /* CC3XX_CONFIG_ECDH_ENABLE */
77