test_suite_psa_crypto_ecp.function (5784B)
1 /* BEGIN_HEADER */ 2 /* Unit tests for internal functions for built-in ECC mechanisms. */ 3 #include <psa/crypto.h> 4 5 #include "psa_crypto_ecp.h" 6 7 #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE) 8 /* 9 * Check if a buffer is all-0 bytes: 10 * return 1 if it is, 11 * 0 if it isn't. 12 * 13 * TODO: we use this in multiple test suites. Move it to framework/tests/src. 14 */ 15 static int buffer_is_all_zero(const uint8_t *buf, size_t size) 16 { 17 for (size_t i = 0; i < size; i++) { 18 if (buf[i] != 0) { 19 return 0; 20 } 21 } 22 return 1; 23 } 24 25 typedef struct { 26 unsigned bit_bot; /* lowest non-forced bit */ 27 unsigned bit_top; /* highest non-forced bit */ 28 } ecc_private_key_stats_t; 29 30 /* Do some sanity checks on an ECC private key. This is not intended to be 31 * a full validity check, just to catch some potential mistakes. */ 32 static int check_ecc_private_key(psa_ecc_family_t family, size_t bits, 33 const uint8_t *key, size_t key_length, 34 ecc_private_key_stats_t *stats) 35 { 36 int ok = 0; 37 38 /* Check the expected length (same calculation for all curves). */ 39 TEST_EQUAL(PSA_BITS_TO_BYTES(bits), key_length); 40 41 /* All-bits zero is invalid and means no key material was copied to the 42 * output buffer, or a grave RNG pluming failure. */ 43 TEST_ASSERT(!buffer_is_all_zero(key, key_length)); 44 45 /* Check the top byte of the value for non-byte-aligned curve sizes. 46 * This is a partial endianness check. */ 47 if (bits % 8 != 0) { 48 /* All supported non-byte-aligned curve sizes are for Weierstrass 49 * curves with a big-endian representation. */ 50 uint8_t top_byte = key[0]; 51 uint8_t mask = 0xff << (bits & 8); 52 TEST_EQUAL(top_byte & mask, 0); 53 } 54 55 /* Check masked bits on Curve25519 and Curve448 scalars. 56 * See RFC 7748 \S4.1 (we expect the "decoded" form here). */ 57 #if defined(MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_255) 58 if (family == PSA_ECC_FAMILY_MONTGOMERY && bits == 255) { 59 TEST_EQUAL(key[0] & 0xf8, key[0]); 60 TEST_EQUAL(key[31] & 0xc0, 0x40); 61 } 62 #endif /* MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_255 */ 63 #if defined(MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_448) 64 if (family == PSA_ECC_FAMILY_MONTGOMERY && bits == 448) { 65 TEST_EQUAL(key[0] & 0xfc, key[0]); 66 TEST_EQUAL(key[55] & 0x80, 0x80); 67 } 68 #endif /* MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_448 */ 69 70 /* Don't bother to check that the value is in the exact permitted range 71 * (1 to p-1 for Weierstrass curves, 2^{n-1} to p-1 for Montgomery curves). 72 * We would need to bring in bignum machinery, and on most curves 73 * the probability of a number being out of range is negligible. 74 */ 75 76 /* Collect statistics on random-valued bits */ 77 /* Defaults for big-endian numbers */ 78 uint8_t bit_bot_mask = 0x01; 79 size_t bit_bot_index = key_length - 1; 80 uint8_t bit_top_mask = (bits % 8 == 0 ? 0x80 : 1 << (bits % 8 - 1)); 81 size_t bit_top_index = 0; 82 if (family == PSA_ECC_FAMILY_MONTGOMERY) { 83 bit_bot_index = 0; 84 bit_top_index = key_length - 1; 85 if (bits == 255) { 86 bit_bot_mask = 0x08; 87 bit_top_mask = 0x20; 88 } else { 89 bit_bot_mask = 0x04; 90 bit_top_mask = 0x40; 91 } 92 } 93 if (key[bit_bot_index] & bit_bot_mask) { 94 ++stats->bit_bot; 95 } 96 if (key[bit_top_index] & bit_top_mask) { 97 ++stats->bit_top; 98 } 99 100 ok = 1; 101 exit: 102 return ok; 103 } 104 #endif 105 106 /* END_HEADER */ 107 108 /* BEGIN_DEPENDENCIES 109 * depends_on:MBEDTLS_PSA_CRYPTO_C:MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY 110 * END_DEPENDENCIES 111 */ 112 113 /* BEGIN_CASE depends_on:MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE */ 114 void generate_key(int family_arg, int bits_arg, 115 int output_size_arg, 116 psa_status_t expected_status) 117 { 118 psa_ecc_family_t family = family_arg; 119 size_t bits = bits_arg; 120 size_t output_size = output_size_arg; 121 122 uint8_t *output = NULL; 123 size_t output_length = SIZE_MAX; 124 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; 125 psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(family)); 126 psa_set_key_bits(&attributes, bits); 127 ecc_private_key_stats_t stats = { 0, 0 }; 128 129 PSA_INIT(); 130 TEST_CALLOC(output, output_size); 131 132 /* In success cases, run multiple iterations so that we can make 133 * statistical observations. */ 134 unsigned iteration_count = expected_status == PSA_SUCCESS ? 256 : 1; 135 for (unsigned i = 0; i < iteration_count; i++) { 136 mbedtls_test_set_step(i); 137 TEST_EQUAL(mbedtls_psa_ecp_generate_key(&attributes, 138 output, output_size, 139 &output_length), 140 expected_status); 141 if (expected_status == PSA_SUCCESS) { 142 TEST_LE_U(output_length, output_size); 143 TEST_ASSERT(check_ecc_private_key(family, bits, 144 output, output_length, 145 &stats)); 146 } 147 } 148 149 if (expected_status == PSA_SUCCESS) { 150 /* For selected bits, check that we saw the values 0 and 1 each 151 * at least some minimum number of times. The iteration count and 152 * the minimum are chosen so that a random failure is unlikely 153 * to more than cryptographic levels. */ 154 unsigned const min_times = 10; 155 TEST_LE_U(min_times, stats.bit_bot); 156 TEST_LE_U(stats.bit_bot, iteration_count - min_times); 157 TEST_LE_U(min_times, stats.bit_top); 158 TEST_LE_U(stats.bit_top, iteration_count - min_times); 159 } 160 161 exit: 162 PSA_DONE(); 163 mbedtls_free(output); 164 } 165 /* END_CASE */