1/* BEGIN_HEADER */
2#include "mbedtls/pk.h"
3#include "mbedtls/pem.h"
4#include "mbedtls/oid.h"
5#include "mbedtls/ecp.h"
6#include "mbedtls/psa_util.h"
7#include "pk_internal.h"
8
9#if defined(MBEDTLS_PSA_CRYPTO_C)
10#include "test/psa_exercise_key.h"
11#endif
12
13#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
14#define HAVE_mbedtls_pk_parse_key_pkcs8_encrypted_der
15#endif
16
17#if defined(MBEDTLS_PSA_CRYPTO_C) && defined(MBEDTLS_FS_IO)
18static int test_psa_bridge(const mbedtls_pk_context *ctx,
19                           psa_key_usage_t usage_flag)
20{
21    switch (usage_flag) {
22        case PSA_KEY_USAGE_SIGN_HASH:
23            mbedtls_test_set_step(0);
24            break;
25        case PSA_KEY_USAGE_SIGN_MESSAGE:
26            mbedtls_test_set_step(1);
27            break;
28        case PSA_KEY_USAGE_DECRYPT:
29            mbedtls_test_set_step(2);
30            break;
31        case PSA_KEY_USAGE_DERIVE:
32            mbedtls_test_set_step(3);
33            break;
34        case PSA_KEY_USAGE_VERIFY_HASH:
35            mbedtls_test_set_step(4);
36            break;
37        case PSA_KEY_USAGE_VERIFY_MESSAGE:
38            mbedtls_test_set_step(5);
39            break;
40        case PSA_KEY_USAGE_ENCRYPT:
41            mbedtls_test_set_step(6);
42            break;
43    }
44
45    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
46    mbedtls_svc_key_id_t psa_key = MBEDTLS_SVC_KEY_ID_INIT;
47    int ok = 0;
48
49    TEST_EQUAL(mbedtls_pk_get_psa_attributes(ctx, usage_flag, &attributes), 0);
50    TEST_EQUAL(mbedtls_pk_import_into_psa(ctx, &attributes, &psa_key), 0);
51    if (!mbedtls_test_key_consistency_psa_pk(psa_key, ctx)) {
52        goto exit;
53    }
54
55    psa_algorithm_t exercise_usage = psa_get_key_usage_flags(&attributes);
56    psa_algorithm_t exercise_alg = psa_get_key_algorithm(&attributes);
57    if (mbedtls_test_can_exercise_psa_algorithm(exercise_alg)) {
58        TEST_ASSERT(mbedtls_test_psa_exercise_key(psa_key,
59                                                  exercise_usage,
60                                                  exercise_alg, 0));
61    }
62
63    mbedtls_test_set_step((unsigned long) -1);
64    ok = 1;
65
66exit:
67    psa_destroy_key(psa_key);
68    psa_reset_key_attributes(&attributes);
69    return ok;
70}
71
72#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
73/* Whether a pk key can do ECDSA. Opaque keys are not supported since this
74 * test suite does not create opaque keys. */
75static int pk_can_ecdsa(const mbedtls_pk_context *ctx)
76{
77    /* Check whether we have an EC key. Unfortunately this also accepts
78     * keys on Montgomery curves, which can only do ECDH, so we'll have
79     * to dig further. */
80    if (!mbedtls_pk_can_do(ctx, MBEDTLS_PK_ECDSA)) {
81        return 0;
82    }
83#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
84    return ctx->ec_family != PSA_ECC_FAMILY_MONTGOMERY;
85#elif defined(MBEDTLS_ECDSA_C)
86    return mbedtls_ecdsa_can_do(mbedtls_pk_ec_ro(*ctx)->grp.id);
87#else
88    return 0;
89#endif
90}
91#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
92#endif /* MBEDTLS_PSA_CRYPTO_C &&  && MBEDTLS_FS_IO */
93
94/* END_HEADER */
95
96/* BEGIN_DEPENDENCIES
97 * depends_on:MBEDTLS_PK_PARSE_C
98 * END_DEPENDENCIES
99 */
100
101/* BEGIN_CASE depends_on:MBEDTLS_RSA_C:MBEDTLS_FS_IO */
102void pk_parse_keyfile_rsa(char *key_file, char *password, int result)
103{
104    mbedtls_pk_context ctx;
105    int res;
106    char *pwd = password;
107
108    mbedtls_pk_init(&ctx);
109    MD_PSA_INIT();
110
111    if (strcmp(pwd, "NULL") == 0) {
112        pwd = NULL;
113    }
114
115    res = mbedtls_pk_parse_keyfile(&ctx, key_file, pwd,
116                                   mbedtls_test_rnd_std_rand, NULL);
117
118    TEST_EQUAL(res, result);
119
120    if (res == 0) {
121        mbedtls_rsa_context *rsa;
122        TEST_ASSERT(mbedtls_pk_can_do(&ctx, MBEDTLS_PK_RSA));
123        rsa = mbedtls_pk_rsa(ctx);
124        TEST_EQUAL(mbedtls_rsa_check_privkey(rsa), 0);
125
126        size_t bitlen = mbedtls_rsa_get_bitlen(rsa);
127        TEST_EQUAL(mbedtls_pk_get_bitlen(&ctx), bitlen);
128        TEST_EQUAL(mbedtls_pk_get_len(&ctx), (bitlen + 7) / 8);
129
130#if defined(MBEDTLS_PSA_CRYPTO_C)
131        PSA_INIT();
132        TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_SIGN_HASH));
133        TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_SIGN_MESSAGE));
134        TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_DECRYPT));
135        TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_VERIFY_HASH));
136        TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_VERIFY_MESSAGE));
137        TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_ENCRYPT));
138#endif
139    }
140
141exit:
142    mbedtls_pk_free(&ctx);
143    PSA_DONE();
144}
145
146/* END_CASE */
147
148/* BEGIN_CASE depends_on:MBEDTLS_RSA_C:MBEDTLS_FS_IO */
149void pk_parse_public_keyfile_rsa(char *key_file, int result)
150{
151    mbedtls_pk_context ctx;
152    int res;
153
154    mbedtls_pk_init(&ctx);
155    MD_PSA_INIT();
156
157    res = mbedtls_pk_parse_public_keyfile(&ctx, key_file);
158
159    TEST_EQUAL(res, result);
160
161    if (res == 0) {
162        mbedtls_rsa_context *rsa;
163        TEST_ASSERT(mbedtls_pk_can_do(&ctx, MBEDTLS_PK_RSA));
164        rsa = mbedtls_pk_rsa(ctx);
165        TEST_EQUAL(mbedtls_rsa_check_pubkey(rsa), 0);
166
167        size_t bitlen = mbedtls_rsa_get_bitlen(rsa);
168        TEST_EQUAL(mbedtls_pk_get_bitlen(&ctx), bitlen);
169        TEST_EQUAL(mbedtls_pk_get_len(&ctx), (bitlen + 7) / 8);
170
171#if defined(MBEDTLS_PSA_CRYPTO_C)
172        PSA_INIT();
173        TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_VERIFY_HASH));
174        TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_VERIFY_MESSAGE));
175        TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_ENCRYPT));
176#endif
177    }
178
179exit:
180    mbedtls_pk_free(&ctx);
181    PSA_DONE();
182}
183/* END_CASE */
184
185/* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_PK_HAVE_ECC_KEYS */
186void pk_parse_public_keyfile_ec(char *key_file, int result)
187{
188    mbedtls_pk_context ctx;
189    int res;
190
191    mbedtls_pk_init(&ctx);
192    MD_OR_USE_PSA_INIT();
193
194    res = mbedtls_pk_parse_public_keyfile(&ctx, key_file);
195
196    TEST_EQUAL(res, result);
197
198    if (res == 0) {
199        TEST_ASSERT(mbedtls_pk_can_do(&ctx, MBEDTLS_PK_ECKEY));
200#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
201        /* No need to check whether the parsed public point is on the curve or
202         * not because this is already done by the internal "pk_get_ecpubkey()"
203         * function */
204#else
205        const mbedtls_ecp_keypair *eckey;
206        eckey = mbedtls_pk_ec_ro(ctx);
207        TEST_EQUAL(mbedtls_ecp_check_pubkey(&eckey->grp, &eckey->Q), 0);
208#endif
209
210#if defined(MBEDTLS_PSA_CRYPTO_C)
211        PSA_INIT();
212        if (pk_can_ecdsa(&ctx)) {
213            TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_VERIFY_HASH));
214            TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_VERIFY_MESSAGE));
215        }
216#endif
217    }
218
219exit:
220    mbedtls_pk_free(&ctx);
221    PSA_DONE();
222}
223/* END_CASE */
224
225/* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_PK_HAVE_ECC_KEYS */
226void pk_parse_keyfile_ec(char *key_file, char *password, int result)
227{
228    mbedtls_pk_context ctx;
229    int res;
230
231    mbedtls_pk_init(&ctx);
232    MD_OR_USE_PSA_INIT();
233
234    res = mbedtls_pk_parse_keyfile(&ctx, key_file, password,
235                                   mbedtls_test_rnd_std_rand, NULL);
236
237    TEST_EQUAL(res, result);
238
239    if (res == 0) {
240        TEST_ASSERT(mbedtls_pk_can_do(&ctx, MBEDTLS_PK_ECKEY));
241#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
242        /* PSA keys are already checked on import so nothing to do here. */
243#else
244        const mbedtls_ecp_keypair *eckey = mbedtls_pk_ec_ro(ctx);
245        TEST_EQUAL(mbedtls_ecp_check_privkey(&eckey->grp, &eckey->d), 0);
246#endif
247
248#if defined(MBEDTLS_PSA_CRYPTO_C)
249        PSA_INIT();
250        TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_DERIVE));
251        if (pk_can_ecdsa(&ctx)) {
252            TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_SIGN_HASH));
253            TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_SIGN_MESSAGE));
254            TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_VERIFY_HASH));
255            TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_VERIFY_MESSAGE));
256        }
257#endif
258    }
259
260exit:
261    mbedtls_pk_free(&ctx);
262    PSA_DONE();
263}
264/* END_CASE */
265
266/* BEGIN_CASE */
267void pk_parse_key(data_t *buf, int result)
268{
269    mbedtls_pk_context pk;
270
271    mbedtls_pk_init(&pk);
272    USE_PSA_INIT();
273
274    TEST_ASSERT(mbedtls_pk_parse_key(&pk, buf->x, buf->len, NULL, 0,
275                                     mbedtls_test_rnd_std_rand, NULL) == result);
276
277exit:
278    mbedtls_pk_free(&pk);
279    USE_PSA_DONE();
280}
281/* END_CASE */
282
283/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS:HAVE_mbedtls_pk_parse_key_pkcs8_encrypted_der */
284void pk_parse_key_encrypted(data_t *buf, data_t *pass, int result)
285{
286    mbedtls_pk_context pk;
287
288    mbedtls_pk_init(&pk);
289    USE_PSA_INIT();
290
291    TEST_EQUAL(mbedtls_pk_parse_key_pkcs8_encrypted_der(&pk, buf->x, buf->len,
292                                                        pass->x, pass->len,
293                                                        mbedtls_test_rnd_std_rand,
294                                                        NULL), result);
295exit:
296    mbedtls_pk_free(&pk);
297    USE_PSA_DONE();
298}
299/* END_CASE */
300
301/* BEGIN_CASE depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_PK_WRITE_C */
302void pk_parse_fix_montgomery(data_t *input_key, data_t *exp_output)
303{
304    /* Montgomery keys have specific bits set to either 0 or 1 depending on
305     * their position. This is enforced during parsing (please see the implementation
306     * of mbedtls_ecp_read_key() for more details). The scope of this function
307     * is to verify this enforcing by feeding the parse algorithm with a x25519
308     * key which does not have those bits set properly. */
309    mbedtls_pk_context pk;
310    unsigned char *output_key = NULL;
311    size_t output_key_len = 0;
312
313    mbedtls_pk_init(&pk);
314    USE_PSA_INIT();
315
316    TEST_EQUAL(mbedtls_pk_parse_key(&pk, input_key->x, input_key->len, NULL, 0,
317                                    mbedtls_test_rnd_std_rand, NULL), 0);
318
319    output_key_len = input_key->len;
320    TEST_CALLOC(output_key, output_key_len);
321    /* output_key_len is updated with the real amount of data written to
322     * output_key buffer. */
323    output_key_len = mbedtls_pk_write_key_der(&pk, output_key, output_key_len);
324    TEST_ASSERT(output_key_len > 0);
325
326    TEST_MEMORY_COMPARE(exp_output->x, exp_output->len, output_key, output_key_len);
327
328exit:
329    if (output_key != NULL) {
330        mbedtls_free(output_key);
331    }
332    mbedtls_pk_free(&pk);
333    USE_PSA_DONE();
334}
335/* END_CASE */
336