1 /*
2  *  Copyright The Mbed TLS Contributors
3  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
4  */
5 
6 
7 #include "psa/crypto.h"
8 #include <string.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include "mbedtls/build_info.h"
12 #include "mbedtls/debug.h"
13 #include "mbedtls/platform.h"
14 
15 #define BUFFER_SIZE 500
16 
17 #define SERVER_PK_VALUE {                                     \
18         0x04, 0xde, 0xa5, 0xe4, 0x5d, 0x0e, 0xa3, 0x7f, 0xc5, \
19         0x66, 0x23, 0x2a, 0x50, 0x8f, 0x4a, 0xd2, 0x0e, 0xa1, \
20         0x3d, 0x47, 0xe4, 0xbf, 0x5f, 0xa4, 0xd5, 0x4a, 0x57, \
21         0xa0, 0xba, 0x01, 0x20, 0x42, 0x08, 0x70, 0x97, 0x49, \
22         0x6e, 0xfc, 0x58, 0x3f, 0xed, 0x8b, 0x24, 0xa5, 0xb9, \
23         0xbe, 0x9a, 0x51, 0xde, 0x06, 0x3f, 0x5a, 0x00, 0xa8, \
24         0xb6, 0x98, 0xa1, 0x6f, 0xd7, 0xf2, 0x9b, 0x54, 0x85, \
25         0xf3, 0x20                                            \
26 }
27 
28 #define KEY_BITS 256
29 
psa_key_agreement_main(void)30 int psa_key_agreement_main(void)
31 {
32     psa_status_t status;
33     psa_key_attributes_t client_attributes = PSA_KEY_ATTRIBUTES_INIT;
34     psa_key_attributes_t server_attributes = PSA_KEY_ATTRIBUTES_INIT;
35     psa_key_attributes_t check_attributes = PSA_KEY_ATTRIBUTES_INIT;
36     psa_key_id_t client_key_id = 0;
37     psa_key_id_t server_key_id = 0;
38     uint8_t client_pk[BUFFER_SIZE] = { 0 };
39     size_t client_pk_len;
40     size_t key_bits;
41     psa_key_type_t key_type;
42 
43     const uint8_t server_pk[] = SERVER_PK_VALUE;
44     uint8_t derived_key[BUFFER_SIZE] = { 0 };
45     size_t derived_key_len;
46 
47     status = psa_crypto_init();
48     if (status != PSA_SUCCESS) {
49         mbedtls_printf("psa_crypto_init failed\n");
50         return EXIT_FAILURE;
51     }
52 
53     psa_set_key_usage_flags(&client_attributes, PSA_KEY_USAGE_DERIVE);
54     psa_set_key_algorithm(&client_attributes, PSA_ALG_ECDH);
55     psa_set_key_type(&client_attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
56     psa_set_key_bits(&client_attributes, KEY_BITS);
57 
58     /* Generate ephemeral key pair */
59     status = psa_generate_key(&client_attributes, &client_key_id);
60     if (status != PSA_SUCCESS) {
61         mbedtls_printf("psa_generate_key failed\n");
62         return EXIT_FAILURE;
63     }
64     status = psa_export_public_key(client_key_id,
65                                    client_pk, sizeof(client_pk),
66                                    &client_pk_len);
67     if (status != PSA_SUCCESS) {
68         mbedtls_printf("psa_export_public_key failed\n");
69         return EXIT_FAILURE;
70     }
71 
72     mbedtls_printf("Client Public Key (%" MBEDTLS_PRINTF_SIZET " bytes):\n", client_pk_len);
73 
74     for (size_t j = 0; j < client_pk_len; j++) {
75         if (j % 8 == 0) {
76             mbedtls_printf("\n    ");
77         }
78         mbedtls_printf("%02x ", client_pk[j]);
79     }
80     mbedtls_printf("\n\n");
81 
82     psa_set_key_usage_flags(&server_attributes, PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT);
83     psa_set_key_algorithm(&server_attributes, PSA_ALG_ECDSA_ANY);
84     psa_set_key_type(&server_attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
85 
86     /* Import server public key */
87     status = psa_import_key(&server_attributes, server_pk, sizeof(server_pk), &server_key_id);
88     if (status != PSA_SUCCESS) {
89         mbedtls_printf("psa_import_key failed\n");
90         return EXIT_FAILURE;
91     }
92 
93     status = psa_get_key_attributes(server_key_id, &check_attributes);
94     if (status != PSA_SUCCESS) {
95         mbedtls_printf("psa_get_key_attributes failed\n");
96         return EXIT_FAILURE;
97     }
98 
99     key_bits = psa_get_key_bits(&check_attributes);
100     if (key_bits != 256) {
101         mbedtls_printf("Incompatible key size!\n");
102         return EXIT_FAILURE;
103     }
104 
105     key_type = psa_get_key_type(&check_attributes);
106     if (key_type != PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1)) {
107         mbedtls_printf("Unsupported key type!\n");
108         return EXIT_FAILURE;
109     }
110 
111     mbedtls_printf("Server Public Key (%" MBEDTLS_PRINTF_SIZET " bytes):\n", sizeof(server_pk));
112 
113     for (size_t j = 0; j < sizeof(server_pk); j++) {
114         if (j % 8 == 0) {
115             mbedtls_printf("\n    ");
116         }
117         mbedtls_printf("%02x ", server_pk[j]);
118     }
119     mbedtls_printf("\n\n");
120 
121     /* Generate ECDHE derived key */
122     status = psa_raw_key_agreement(PSA_ALG_ECDH,                        // algorithm
123                                    client_key_id,                   // client secret key
124                                    server_pk, sizeof(server_pk),        // server public key
125                                    derived_key, sizeof(derived_key),    // buffer to store derived key
126                                    &derived_key_len);
127     if (status != PSA_SUCCESS) {
128         mbedtls_printf("psa_raw_key_agreement failed\n");
129         return EXIT_FAILURE;
130     }
131 
132     mbedtls_printf("Derived Key (%" MBEDTLS_PRINTF_SIZET " bytes):\n", derived_key_len);
133 
134     for (size_t j = 0; j < derived_key_len; j++) {
135         if (j % 8 == 0) {
136             mbedtls_printf("\n    ");
137         }
138         mbedtls_printf("%02x ", derived_key[j]);
139     }
140     mbedtls_printf("\n");
141 
142     psa_destroy_key(server_key_id);
143     psa_destroy_key(client_key_id);
144     mbedtls_psa_crypto_free();
145     return EXIT_SUCCESS;
146 }
147