1/* BEGIN_HEADER */ 2#include "mbedtls/pk.h" 3#include "mbedtls/pem.h" 4#include "mbedtls/oid.h" 5#include "psa/crypto_sizes.h" 6 7typedef enum { 8 TEST_PEM, 9 TEST_DER 10} pkwrite_file_format_t; 11 12/* Helper function for removing "\r" chars from a buffer. */ 13static 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; 22 memmove(&in_str[i], &in_str[i+1], chars_left); 23 } else { 24 in_str[i] = '\0'; 25 } 26 *len = *len - 1; 27 } 28 } 29} 30 31static void pk_write_check_common(char *key_file, int is_public_key, int is_der) 32{ 33 mbedtls_pk_context key; 34 unsigned char *buf = NULL; 35 unsigned char *check_buf = NULL; 36 unsigned char *start_buf; 37 size_t buf_len, check_buf_len; 38 int ret; 39 40 mbedtls_pk_init(&key); 41 USE_PSA_INIT(); 42 43 /* Note: if mbedtls_pk_load_file() successfully reads the file, then 44 it also allocates check_buf, which should be freed on exit */ 45 TEST_EQUAL(mbedtls_pk_load_file(key_file, &check_buf, &check_buf_len), 0); 46 TEST_ASSERT(check_buf_len > 0); 47 48 /* Windows' line ending is different from the Linux's one ("\r\n" vs "\n"). 49 * Git treats PEM files as text, so when on Windows, it replaces new lines 50 * with "\r\n" on checkout. 51 * Unfortunately mbedtls_pk_load_file() loads files in binary format, 52 * while mbedtls_pk_write_pubkey_pem() goes through the I/O layer which 53 * uses "\n" for newlines in both Windows and Linux. 54 * Here we remove the extra "\r" so that "buf" and "check_buf" can be 55 * easily compared later. */ 56 if (!is_der) { 57 fix_new_lines(check_buf, &check_buf_len); 58 } 59 TEST_ASSERT(check_buf_len > 0); 60 61 TEST_CALLOC(buf, check_buf_len); 62 63 if (is_public_key) { 64 TEST_EQUAL(mbedtls_pk_parse_public_keyfile(&key, key_file), 0); 65 if (is_der) { 66 ret = mbedtls_pk_write_pubkey_der(&key, buf, check_buf_len); 67 } else { 68#if defined(MBEDTLS_PEM_WRITE_C) 69 ret = mbedtls_pk_write_pubkey_pem(&key, buf, check_buf_len); 70#else 71 ret = MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; 72#endif 73 } 74 } else { 75 TEST_EQUAL(mbedtls_pk_parse_keyfile(&key, key_file, NULL), 0); 76 if (is_der) { 77 ret = mbedtls_pk_write_key_der(&key, buf, check_buf_len); 78 } else { 79#if defined(MBEDTLS_PEM_WRITE_C) 80 ret = mbedtls_pk_write_key_pem(&key, buf, check_buf_len); 81#else 82 ret = MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; 83#endif 84 } 85 } 86 87 if (is_der) { 88 TEST_LE_U(1, ret); 89 buf_len = ret; 90 start_buf = buf + check_buf_len - buf_len; 91 } else { 92 TEST_EQUAL(ret, 0); 93 buf_len = strlen((char *) buf) + 1; /* +1 takes the string terminator into account */ 94 start_buf = buf; 95 } 96 97 TEST_MEMORY_COMPARE(start_buf, buf_len, check_buf, check_buf_len); 98 99exit: 100 mbedtls_free(buf); 101 mbedtls_free(check_buf); 102 mbedtls_pk_free(&key); 103 USE_PSA_DONE(); 104} 105/* END_HEADER */ 106 107/* BEGIN_DEPENDENCIES 108 * depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_BIGNUM_C:MBEDTLS_FS_IO 109 * END_DEPENDENCIES 110 */ 111 112/* BEGIN_CASE */ 113void pk_write_pubkey_check(char *key_file, int is_der) 114{ 115 pk_write_check_common(key_file, 1, is_der); 116 goto exit; /* make the compiler happy */ 117} 118/* END_CASE */ 119 120/* BEGIN_CASE */ 121void pk_write_key_check(char *key_file, int is_der) 122{ 123 pk_write_check_common(key_file, 0, is_der); 124 goto exit; /* make the compiler happy */ 125} 126/* END_CASE */ 127 128/* BEGIN_CASE */ 129void pk_write_public_from_private(char *priv_key_file, char *pub_key_file) 130{ 131 mbedtls_pk_context priv_key; 132 uint8_t *derived_key_raw = NULL; 133 size_t derived_key_len = 0; 134 uint8_t *pub_key_raw = NULL; 135 size_t pub_key_len = 0; 136#if defined(MBEDTLS_USE_PSA_CRYPTO) 137 mbedtls_svc_key_id_t opaque_key_id = MBEDTLS_SVC_KEY_ID_INIT; 138#endif /* MBEDTLS_USE_PSA_CRYPTO */ 139 140 mbedtls_pk_init(&priv_key); 141 USE_PSA_INIT(); 142 143 TEST_EQUAL(mbedtls_pk_parse_keyfile(&priv_key, priv_key_file, NULL), 0); 144 TEST_EQUAL(mbedtls_pk_load_file(pub_key_file, &pub_key_raw, 145 &pub_key_len), 0); 146 147 derived_key_len = pub_key_len; 148 TEST_CALLOC(derived_key_raw, derived_key_len); 149 150 TEST_EQUAL(mbedtls_pk_write_pubkey_der(&priv_key, derived_key_raw, 151 derived_key_len), pub_key_len); 152 153 TEST_MEMORY_COMPARE(derived_key_raw, derived_key_len, 154 pub_key_raw, pub_key_len); 155 156#if defined(MBEDTLS_USE_PSA_CRYPTO) 157 mbedtls_platform_zeroize(derived_key_raw, derived_key_len); 158 159 TEST_EQUAL(mbedtls_pk_wrap_as_opaque(&priv_key, &opaque_key_id, 160 PSA_ALG_NONE), 0); 161 162 TEST_EQUAL(mbedtls_pk_write_pubkey_der(&priv_key, derived_key_raw, 163 derived_key_len), pub_key_len); 164 165 TEST_MEMORY_COMPARE(derived_key_raw, derived_key_len, 166 pub_key_raw, pub_key_len); 167#endif /* MBEDTLS_USE_PSA_CRYPTO */ 168 169exit: 170#if defined(MBEDTLS_USE_PSA_CRYPTO) 171 psa_destroy_key(opaque_key_id); 172#endif /* MBEDTLS_USE_PSA_CRYPTO */ 173 mbedtls_free(derived_key_raw); 174 mbedtls_free(pub_key_raw); 175 mbedtls_pk_free(&priv_key); 176 USE_PSA_DONE(); 177} 178/* END_CASE */ 179