| Paul Bakker | c7bb02b | 2013-09-15 14:54:56 +0200 | [diff] [blame] | 1 | /* BEGIN_HEADER */ | 
| Valerio Setti | 639d567 | 2024-01-17 11:04:56 +0100 | [diff] [blame] | 2 | #include "pk_internal.h" | 
| Manuel Pégourié-Gonnard | 7f80997 | 2015-03-09 17:05:11 +0000 | [diff] [blame] | 3 | #include "mbedtls/pem.h" | 
|  | 4 | #include "mbedtls/oid.h" | 
| Valerio Setti | 1751341 | 2023-04-26 14:48:43 +0200 | [diff] [blame] | 5 | #include "psa/crypto_sizes.h" | 
| Valerio Setti | 8959095 | 2023-04-17 17:34:09 +0200 | [diff] [blame] | 6 |  | 
| Valerio Setti | c9cb532 | 2023-04-18 11:20:36 +0200 | [diff] [blame] | 7 | typedef enum { | 
|  | 8 | TEST_PEM, | 
|  | 9 | TEST_DER | 
|  | 10 | } pkwrite_file_format_t; | 
|  | 11 |  | 
| Valerio Setti | 547b3a4 | 2023-04-24 10:24:37 +0200 | [diff] [blame] | 12 | /* Helper function for removing "\r" chars from a buffer. */ | 
| Valerio Setti | 7bacaf8 | 2023-04-24 08:52:16 +0200 | [diff] [blame] | 13 | static void fix_new_lines(unsigned char *in_str, size_t *len) | 
|  | 14 | { | 
|  | 15 | size_t chars_left; | 
|  | 16 | unsigned int i; | 
|  | 17 |  | 
|  | 18 | for (i = 0; (i < *len) && (*len > 0); i++) { | 
|  | 19 | if (in_str[i] == '\r') { | 
|  | 20 | if (i < (*len - 1)) { | 
|  | 21 | chars_left = *len - i - 1; | 
| Valerio Setti | bf974b9 | 2023-04-24 10:26:24 +0200 | [diff] [blame] | 22 | memmove(&in_str[i], &in_str[i+1], chars_left); | 
| Valerio Setti | 7bacaf8 | 2023-04-24 08:52:16 +0200 | [diff] [blame] | 23 | } else { | 
|  | 24 | in_str[i] = '\0'; | 
|  | 25 | } | 
|  | 26 | *len = *len - 1; | 
|  | 27 | } | 
|  | 28 | } | 
|  | 29 | } | 
|  | 30 |  | 
| valerio | f6853a8 | 2023-05-31 12:00:11 +0200 | [diff] [blame] | 31 | static int pk_write_any_key(mbedtls_pk_context *pk, unsigned char **p, | 
|  | 32 | size_t *buf_len, int is_public_key, int is_der) | 
|  | 33 | { | 
|  | 34 | int ret = 0; | 
|  | 35 |  | 
|  | 36 | if (is_der) { | 
|  | 37 | if (is_public_key) { | 
|  | 38 | ret = mbedtls_pk_write_pubkey_der(pk, *p, *buf_len); | 
|  | 39 | } else { | 
|  | 40 | ret = mbedtls_pk_write_key_der(pk, *p, *buf_len); | 
|  | 41 | } | 
|  | 42 | if (ret <= 0) { | 
|  | 43 | return ret; | 
|  | 44 | } | 
|  | 45 |  | 
|  | 46 | *p = *p + *buf_len - ret; | 
|  | 47 | *buf_len = ret; | 
|  | 48 | } else { | 
|  | 49 | #if defined(MBEDTLS_PEM_WRITE_C) | 
|  | 50 | if (is_public_key) { | 
|  | 51 | ret = mbedtls_pk_write_pubkey_pem(pk, *p, *buf_len); | 
|  | 52 | } else { | 
|  | 53 | ret = mbedtls_pk_write_key_pem(pk, *p, *buf_len); | 
|  | 54 | } | 
|  | 55 | if (ret != 0) { | 
|  | 56 | return ret; | 
|  | 57 | } | 
|  | 58 |  | 
|  | 59 | *buf_len = strlen((char *) *p) + 1; /* +1 takes the string terminator into account */ | 
|  | 60 | #else | 
|  | 61 | return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; | 
|  | 62 | #endif | 
|  | 63 | } | 
|  | 64 |  | 
|  | 65 | return 0; | 
|  | 66 | } | 
|  | 67 |  | 
| Valerio Setti | c60bc5e | 2023-04-17 18:43:06 +0200 | [diff] [blame] | 68 | static void pk_write_check_common(char *key_file, int is_public_key, int is_der) | 
| Valerio Setti | 8959095 | 2023-04-17 17:34:09 +0200 | [diff] [blame] | 69 | { | 
|  | 70 | mbedtls_pk_context key; | 
| Gilles Peskine | 21e46b3 | 2023-10-17 16:35:20 +0200 | [diff] [blame] | 71 | mbedtls_pk_init(&key); | 
| Valerio Setti | 8959095 | 2023-04-17 17:34:09 +0200 | [diff] [blame] | 72 | unsigned char *buf = NULL; | 
|  | 73 | unsigned char *check_buf = NULL; | 
| Valerio Setti | c60bc5e | 2023-04-17 18:43:06 +0200 | [diff] [blame] | 74 | unsigned char *start_buf; | 
| Valerio Setti | 3401b30 | 2023-04-18 10:42:53 +0200 | [diff] [blame] | 75 | size_t buf_len, check_buf_len; | 
| valerio | f6853a8 | 2023-05-31 12:00:11 +0200 | [diff] [blame] | 76 | #if defined(MBEDTLS_USE_PSA_CRYPTO) | 
|  | 77 | mbedtls_svc_key_id_t opaque_id = MBEDTLS_SVC_KEY_ID_INIT; | 
| Valerio Setti | 1fa2f6e | 2024-02-27 08:11:25 +0100 | [diff] [blame] | 78 | psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; | 
| valerio | f6853a8 | 2023-05-31 12:00:11 +0200 | [diff] [blame] | 79 | #endif /* MBEDTLS_USE_PSA_CRYPTO */ | 
|  | 80 |  | 
|  | 81 | USE_PSA_INIT(); | 
| Valerio Setti | 8959095 | 2023-04-17 17:34:09 +0200 | [diff] [blame] | 82 |  | 
|  | 83 | /* Note: if mbedtls_pk_load_file() successfully reads the file, then | 
|  | 84 | it also allocates check_buf, which should be freed on exit */ | 
| Valerio Setti | 3401b30 | 2023-04-18 10:42:53 +0200 | [diff] [blame] | 85 | TEST_EQUAL(mbedtls_pk_load_file(key_file, &check_buf, &check_buf_len), 0); | 
| Valerio Setti | 8959095 | 2023-04-17 17:34:09 +0200 | [diff] [blame] | 86 | TEST_ASSERT(check_buf_len > 0); | 
|  | 87 |  | 
| Valerio Setti | 7bacaf8 | 2023-04-24 08:52:16 +0200 | [diff] [blame] | 88 | /* Windows' line ending is different from the Linux's one ("\r\n" vs "\n"). | 
|  | 89 | * Git treats PEM files as text, so when on Windows, it replaces new lines | 
|  | 90 | * with "\r\n" on checkout. | 
|  | 91 | * Unfortunately mbedtls_pk_load_file() loads files in binary format, | 
|  | 92 | * while mbedtls_pk_write_pubkey_pem() goes through the I/O layer which | 
|  | 93 | * uses "\n" for newlines in both Windows and Linux. | 
|  | 94 | * Here we remove the extra "\r" so that "buf" and "check_buf" can be | 
|  | 95 | * easily compared later. */ | 
|  | 96 | if (!is_der) { | 
|  | 97 | fix_new_lines(check_buf, &check_buf_len); | 
|  | 98 | } | 
|  | 99 | TEST_ASSERT(check_buf_len > 0); | 
|  | 100 |  | 
| Tom Cosgrove | 05b2a87 | 2023-07-21 11:31:13 +0100 | [diff] [blame] | 101 | TEST_CALLOC(buf, check_buf_len); | 
| Valerio Setti | 8959095 | 2023-04-17 17:34:09 +0200 | [diff] [blame] | 102 |  | 
| Valerio Setti | 8959095 | 2023-04-17 17:34:09 +0200 | [diff] [blame] | 103 | if (is_public_key) { | 
| Valerio Setti | 3401b30 | 2023-04-18 10:42:53 +0200 | [diff] [blame] | 104 | TEST_EQUAL(mbedtls_pk_parse_public_keyfile(&key, key_file), 0); | 
| Valerio Setti | 8959095 | 2023-04-17 17:34:09 +0200 | [diff] [blame] | 105 | } else { | 
| Valerio Setti | 3401b30 | 2023-04-18 10:42:53 +0200 | [diff] [blame] | 106 | TEST_EQUAL(mbedtls_pk_parse_keyfile(&key, key_file, NULL, | 
| Valerio Setti | 2280895 | 2023-04-18 12:57:52 +0200 | [diff] [blame] | 107 | mbedtls_test_rnd_std_rand, NULL), 0); | 
| Valerio Setti | 8959095 | 2023-04-17 17:34:09 +0200 | [diff] [blame] | 108 | } | 
| Valerio Setti | 8959095 | 2023-04-17 17:34:09 +0200 | [diff] [blame] | 109 |  | 
| valerio | f6853a8 | 2023-05-31 12:00:11 +0200 | [diff] [blame] | 110 | start_buf = buf; | 
|  | 111 | buf_len = check_buf_len; | 
|  | 112 | TEST_EQUAL(pk_write_any_key(&key, &start_buf, &buf_len, is_public_key, | 
|  | 113 | is_der), 0); | 
| Valerio Setti | c60bc5e | 2023-04-17 18:43:06 +0200 | [diff] [blame] | 114 |  | 
| Tom Cosgrove | e4e9e7d | 2023-07-21 11:40:20 +0100 | [diff] [blame] | 115 | TEST_MEMORY_COMPARE(start_buf, buf_len, check_buf, check_buf_len); | 
| Valerio Setti | 8959095 | 2023-04-17 17:34:09 +0200 | [diff] [blame] | 116 |  | 
| valerio | f6853a8 | 2023-05-31 12:00:11 +0200 | [diff] [blame] | 117 | #if defined(MBEDTLS_USE_PSA_CRYPTO) | 
|  | 118 | /* Verify that pk_write works also for opaque private keys */ | 
|  | 119 | if (!is_public_key) { | 
|  | 120 | memset(buf, 0, check_buf_len); | 
| Valerio Setti | 1fa2f6e | 2024-02-27 08:11:25 +0100 | [diff] [blame] | 121 | /* Turn the key PK context into an opaque one. | 
|  | 122 | * Note: set some practical usage for the key to make get_psa_attributes() happy. */ | 
|  | 123 | TEST_EQUAL(mbedtls_pk_get_psa_attributes(&key, PSA_KEY_USAGE_SIGN_MESSAGE, &key_attr), 0); | 
|  | 124 | TEST_EQUAL(mbedtls_pk_import_into_psa(&key, &key_attr, &opaque_id), 0); | 
|  | 125 | mbedtls_pk_free(&key); | 
|  | 126 | mbedtls_pk_init(&key); | 
|  | 127 | TEST_EQUAL(mbedtls_pk_setup_opaque(&key, opaque_id), 0); | 
| valerio | f6853a8 | 2023-05-31 12:00:11 +0200 | [diff] [blame] | 128 | start_buf = buf; | 
|  | 129 | buf_len = check_buf_len; | 
|  | 130 | TEST_EQUAL(pk_write_any_key(&key, &start_buf, &buf_len, is_public_key, | 
|  | 131 | is_der), 0); | 
|  | 132 |  | 
| Tom Cosgrove | e4e9e7d | 2023-07-21 11:40:20 +0100 | [diff] [blame] | 133 | TEST_MEMORY_COMPARE(start_buf, buf_len, check_buf, check_buf_len); | 
| valerio | f6853a8 | 2023-05-31 12:00:11 +0200 | [diff] [blame] | 134 | } | 
|  | 135 | #endif /* MBEDTLS_USE_PSA_CRYPTO */ | 
|  | 136 |  | 
| Valerio Setti | 8959095 | 2023-04-17 17:34:09 +0200 | [diff] [blame] | 137 | exit: | 
| valerio | f6853a8 | 2023-05-31 12:00:11 +0200 | [diff] [blame] | 138 | #if defined(MBEDTLS_USE_PSA_CRYPTO) | 
|  | 139 | psa_destroy_key(opaque_id); | 
|  | 140 | #endif /* MBEDTLS_USE_PSA_CRYPTO */ | 
| Valerio Setti | 8959095 | 2023-04-17 17:34:09 +0200 | [diff] [blame] | 141 | mbedtls_free(buf); | 
|  | 142 | mbedtls_free(check_buf); | 
|  | 143 | mbedtls_pk_free(&key); | 
| Valerio Setti | 14bfdbf | 2023-04-24 13:53:21 +0200 | [diff] [blame] | 144 | USE_PSA_DONE(); | 
| Valerio Setti | 8959095 | 2023-04-17 17:34:09 +0200 | [diff] [blame] | 145 | } | 
| Paul Bakker | c7bb02b | 2013-09-15 14:54:56 +0200 | [diff] [blame] | 146 | /* END_HEADER */ | 
|  | 147 |  | 
|  | 148 | /* BEGIN_DEPENDENCIES | 
| Valerio Setti | c5d85e5 | 2023-07-26 18:12:23 +0200 | [diff] [blame] | 149 | * depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_FS_IO | 
| Paul Bakker | c7bb02b | 2013-09-15 14:54:56 +0200 | [diff] [blame] | 150 | * END_DEPENDENCIES | 
|  | 151 | */ | 
|  | 152 |  | 
| Valerio Setti | 15cac17 | 2023-04-18 11:25:30 +0200 | [diff] [blame] | 153 | /* BEGIN_CASE */ | 
| Valerio Setti | c60bc5e | 2023-04-17 18:43:06 +0200 | [diff] [blame] | 154 | void pk_write_pubkey_check(char *key_file, int is_der) | 
| Paul Bakker | c7bb02b | 2013-09-15 14:54:56 +0200 | [diff] [blame] | 155 | { | 
| Valerio Setti | c60bc5e | 2023-04-17 18:43:06 +0200 | [diff] [blame] | 156 | pk_write_check_common(key_file, 1, is_der); | 
| Valerio Setti | 8959095 | 2023-04-17 17:34:09 +0200 | [diff] [blame] | 157 | goto exit; /* make the compiler happy */ | 
| Paul Bakker | c7bb02b | 2013-09-15 14:54:56 +0200 | [diff] [blame] | 158 | } | 
|  | 159 | /* END_CASE */ | 
|  | 160 |  | 
| Valerio Setti | 15cac17 | 2023-04-18 11:25:30 +0200 | [diff] [blame] | 161 | /* BEGIN_CASE */ | 
| Valerio Setti | c60bc5e | 2023-04-17 18:43:06 +0200 | [diff] [blame] | 162 | void pk_write_key_check(char *key_file, int is_der) | 
| Paul Bakker | c7bb02b | 2013-09-15 14:54:56 +0200 | [diff] [blame] | 163 | { | 
| Valerio Setti | c60bc5e | 2023-04-17 18:43:06 +0200 | [diff] [blame] | 164 | pk_write_check_common(key_file, 0, is_der); | 
| Valerio Setti | 8959095 | 2023-04-17 17:34:09 +0200 | [diff] [blame] | 165 | goto exit; /* make the compiler happy */ | 
| Paul Bakker | c7bb02b | 2013-09-15 14:54:56 +0200 | [diff] [blame] | 166 | } | 
|  | 167 | /* END_CASE */ | 
| Valerio Setti | 1751341 | 2023-04-26 14:48:43 +0200 | [diff] [blame] | 168 |  | 
|  | 169 | /* BEGIN_CASE */ | 
| Valerio Setti | f545171 | 2023-04-27 10:52:57 +0200 | [diff] [blame] | 170 | void pk_write_public_from_private(char *priv_key_file, char *pub_key_file) | 
| Valerio Setti | 1751341 | 2023-04-26 14:48:43 +0200 | [diff] [blame] | 171 | { | 
| Valerio Setti | f545171 | 2023-04-27 10:52:57 +0200 | [diff] [blame] | 172 | mbedtls_pk_context priv_key; | 
|  | 173 | uint8_t *derived_key_raw = NULL; | 
| Valerio Setti | 1751341 | 2023-04-26 14:48:43 +0200 | [diff] [blame] | 174 | size_t derived_key_len = 0; | 
| Valerio Setti | f545171 | 2023-04-27 10:52:57 +0200 | [diff] [blame] | 175 | uint8_t *pub_key_raw = NULL; | 
| Valerio Setti | 1751341 | 2023-04-26 14:48:43 +0200 | [diff] [blame] | 176 | size_t pub_key_len = 0; | 
|  | 177 | #if defined(MBEDTLS_USE_PSA_CRYPTO) | 
|  | 178 | mbedtls_svc_key_id_t opaque_key_id = MBEDTLS_SVC_KEY_ID_INIT; | 
| Valerio Setti | 1fa2f6e | 2024-02-27 08:11:25 +0100 | [diff] [blame] | 179 | psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; | 
| Valerio Setti | 1751341 | 2023-04-26 14:48:43 +0200 | [diff] [blame] | 180 | #endif /* MBEDTLS_USE_PSA_CRYPTO */ | 
|  | 181 |  | 
|  | 182 | mbedtls_pk_init(&priv_key); | 
| Valerio Setti | 1751341 | 2023-04-26 14:48:43 +0200 | [diff] [blame] | 183 | USE_PSA_INIT(); | 
|  | 184 |  | 
| Valerio Setti | 1751341 | 2023-04-26 14:48:43 +0200 | [diff] [blame] | 185 | TEST_EQUAL(mbedtls_pk_parse_keyfile(&priv_key, priv_key_file, NULL, | 
|  | 186 | mbedtls_test_rnd_std_rand, NULL), 0); | 
| Valerio Setti | f545171 | 2023-04-27 10:52:57 +0200 | [diff] [blame] | 187 | TEST_EQUAL(mbedtls_pk_load_file(pub_key_file, &pub_key_raw, | 
|  | 188 | &pub_key_len), 0); | 
| Valerio Setti | 1751341 | 2023-04-26 14:48:43 +0200 | [diff] [blame] | 189 |  | 
| Valerio Setti | f545171 | 2023-04-27 10:52:57 +0200 | [diff] [blame] | 190 | derived_key_len = pub_key_len; | 
| Tom Cosgrove | 05b2a87 | 2023-07-21 11:31:13 +0100 | [diff] [blame] | 191 | TEST_CALLOC(derived_key_raw, derived_key_len); | 
| Valerio Setti | 1751341 | 2023-04-26 14:48:43 +0200 | [diff] [blame] | 192 |  | 
| Valerio Setti | 9a855f2 | 2023-04-27 12:07:23 +0200 | [diff] [blame] | 193 | TEST_EQUAL(mbedtls_pk_write_pubkey_der(&priv_key, derived_key_raw, | 
|  | 194 | derived_key_len), pub_key_len); | 
| Valerio Setti | 1751341 | 2023-04-26 14:48:43 +0200 | [diff] [blame] | 195 |  | 
| Tom Cosgrove | e4e9e7d | 2023-07-21 11:40:20 +0100 | [diff] [blame] | 196 | TEST_MEMORY_COMPARE(derived_key_raw, derived_key_len, | 
| Tom Cosgrove | 0540fe7 | 2023-07-27 14:17:27 +0100 | [diff] [blame] | 197 | pub_key_raw, pub_key_len); | 
| Valerio Setti | 1751341 | 2023-04-26 14:48:43 +0200 | [diff] [blame] | 198 |  | 
|  | 199 | #if defined(MBEDTLS_USE_PSA_CRYPTO) | 
| Tom Cosgrove | 351a391 | 2023-09-01 09:54:04 +0100 | [diff] [blame] | 200 | mbedtls_platform_zeroize(derived_key_raw, derived_key_len); | 
| Valerio Setti | 1751341 | 2023-04-26 14:48:43 +0200 | [diff] [blame] | 201 |  | 
| Valerio Setti | 1fa2f6e | 2024-02-27 08:11:25 +0100 | [diff] [blame] | 202 | /* Turn the priv_key PK context into an opaque one. */ | 
|  | 203 | TEST_EQUAL(mbedtls_pk_get_psa_attributes(&priv_key, PSA_KEY_USAGE_SIGN_HASH, &key_attr), 0); | 
|  | 204 | TEST_EQUAL(mbedtls_pk_import_into_psa(&priv_key, &key_attr, &opaque_key_id), 0); | 
|  | 205 | mbedtls_pk_free(&priv_key); | 
|  | 206 | mbedtls_pk_init(&priv_key); | 
|  | 207 | TEST_EQUAL(mbedtls_pk_setup_opaque(&priv_key, opaque_key_id), 0); | 
| Valerio Setti | 1751341 | 2023-04-26 14:48:43 +0200 | [diff] [blame] | 208 |  | 
| Valerio Setti | 9a855f2 | 2023-04-27 12:07:23 +0200 | [diff] [blame] | 209 | TEST_EQUAL(mbedtls_pk_write_pubkey_der(&priv_key, derived_key_raw, | 
|  | 210 | derived_key_len), pub_key_len); | 
| Valerio Setti | 1751341 | 2023-04-26 14:48:43 +0200 | [diff] [blame] | 211 |  | 
| Tom Cosgrove | e4e9e7d | 2023-07-21 11:40:20 +0100 | [diff] [blame] | 212 | TEST_MEMORY_COMPARE(derived_key_raw, derived_key_len, | 
| Tom Cosgrove | 0540fe7 | 2023-07-27 14:17:27 +0100 | [diff] [blame] | 213 | pub_key_raw, pub_key_len); | 
| Valerio Setti | 1751341 | 2023-04-26 14:48:43 +0200 | [diff] [blame] | 214 | #endif /* MBEDTLS_USE_PSA_CRYPTO */ | 
|  | 215 |  | 
|  | 216 | exit: | 
|  | 217 | #if defined(MBEDTLS_USE_PSA_CRYPTO) | 
|  | 218 | psa_destroy_key(opaque_key_id); | 
|  | 219 | #endif /* MBEDTLS_USE_PSA_CRYPTO */ | 
| Valerio Setti | f545171 | 2023-04-27 10:52:57 +0200 | [diff] [blame] | 220 | mbedtls_free(derived_key_raw); | 
|  | 221 | mbedtls_free(pub_key_raw); | 
| Valerio Setti | 1751341 | 2023-04-26 14:48:43 +0200 | [diff] [blame] | 222 | mbedtls_pk_free(&priv_key); | 
|  | 223 | USE_PSA_DONE(); | 
|  | 224 | } | 
|  | 225 | /* END_CASE */ |