1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(C) 2023 Marvell. 3 */ 4 5 #include <string.h> 6 #include <time.h> 7 #include <stdio.h> 8 #include <sys/types.h> 9 #include <unistd.h> 10 11 #ifdef USE_OPENSSL 12 #include <openssl/bn.h> 13 #include <openssl/rand.h> 14 #endif /* USE_OPENSSL */ 15 16 #include <rte_cryptodev.h> 17 #include <rte_malloc.h> 18 19 #include "fips_validation.h" 20 21 #define TESTTYPE_JSON_STR "testType" 22 #define CURVE_JSON_STR "curve" 23 #define PH_JSON_STR "preHash" 24 25 #define MSG_JSON_STR "message" 26 #define CTX_JSON_STR "context" 27 #define Q_JSON_STR "q" 28 #define SIG_JSON_STR "signature" 29 30 #ifdef USE_JANSSON 31 struct { 32 uint8_t type; 33 const char *desc; 34 } eddsa_test_types[] = { 35 {EDDSA_AFT, "AFT"}, 36 {EDDSA_BFT, "BFT"} 37 }; 38 39 struct { 40 enum rte_crypto_curve_id curve_id; 41 const char *desc; 42 } eddsa_curve_ids[] = { 43 {RTE_CRYPTO_EC_GROUP_ED25519, "ED-25519"}, 44 {RTE_CRYPTO_EC_GROUP_ED448, "ED-448"}, 45 }; 46 47 struct { 48 uint8_t curve_len; 49 const char *desc; 50 } eddsa_curve_len[] = { 51 {64, "ED-25519"}, 52 {114, "ED-448"}, 53 }; 54 55 #ifdef USE_OPENSSL 56 #define MAX_TRIES 10 57 static int 58 prepare_vec_eddsa(void) 59 { 60 BIGNUM *pkey = NULL, *order = NULL; 61 int ret = -1, j; 62 unsigned long pid; 63 64 /* For EdDSA prime fields, order of base points (RFC 8032 Section 5.1 and 5.2). 65 */ 66 static const char * const orderstr[] = { 67 "7237005577332262213973186563042994240857116359379907606001950938285454250989", 68 "181709681073901722637330951972001133588410340171829515070372549795146003961539585716195755291692375963310293709091662304773755859649779", 69 }; 70 71 pid = getpid(); 72 RAND_seed(&pid, sizeof(pid)); 73 74 if (!RAND_status()) 75 return -1; 76 77 order = BN_new(); 78 if (!order) 79 goto err; 80 81 j = info.interim_info.eddsa_data.curve_id - RTE_CRYPTO_EC_GROUP_ED25519; 82 if (!BN_hex2bn(&order, orderstr[j])) 83 goto err; 84 85 pkey = BN_new(); 86 if (!pkey) 87 goto err; 88 89 for (j = 0; j < MAX_TRIES; j++) { 90 /* pkey should be in [1, order - 1] */ 91 if (!BN_rand_range(pkey, order)) 92 goto err; 93 94 if (!BN_is_zero(pkey)) 95 break; 96 } 97 98 if (j == MAX_TRIES) 99 goto err; 100 101 parse_uint8_hex_str("", BN_bn2hex(pkey), &vec.eddsa.pkey); 102 103 ret = 0; 104 err: 105 BN_free(order); 106 BN_free(pkey); 107 return ret; 108 } 109 #else 110 static int 111 prepare_vec_eddsa(void) 112 { 113 /* 114 * Generate EdDSA values. 115 */ 116 return -ENOTSUP; 117 } 118 #endif /* USE_OPENSSL */ 119 120 static int 121 parse_test_eddsa_json_interim_writeback(struct fips_val *val) 122 { 123 RTE_SET_USED(val); 124 125 if (info.op == FIPS_TEST_ASYM_SIGGEN) { 126 /* For siggen tests, EdDSA values can be created soon after 127 * the test group data are parsed. 128 */ 129 if (vec.eddsa.pkey.val) { 130 rte_free(vec.eddsa.pkey.val); 131 vec.eddsa.pkey.val = NULL; 132 } 133 134 if (prepare_vec_eddsa() < 0) 135 return -1; 136 137 info.interim_info.eddsa_data.pubkey_gen = 1; 138 } 139 140 return 0; 141 } 142 143 static int 144 post_test_eddsa_json_interim_writeback(struct fips_val *val) 145 { 146 RTE_SET_USED(val); 147 148 if (info.op == FIPS_TEST_ASYM_KEYGEN) { 149 json_t *obj; 150 151 writeback_hex_str("", info.one_line_text, &vec.eddsa.q); 152 obj = json_string(info.one_line_text); 153 json_object_set_new(json_info.json_write_group, "q", obj); 154 } 155 156 return 0; 157 } 158 159 static int 160 parse_test_eddsa_json_writeback(struct fips_val *val) 161 { 162 json_t *tcId; 163 164 RTE_SET_USED(val); 165 166 tcId = json_object_get(json_info.json_test_case, "tcId"); 167 168 json_info.json_write_case = json_object(); 169 json_object_set(json_info.json_write_case, "tcId", tcId); 170 171 if (info.op == FIPS_TEST_ASYM_SIGGEN) { 172 json_t *obj; 173 174 writeback_hex_str("", info.one_line_text, &vec.eddsa.sign); 175 obj = json_string(info.one_line_text); 176 json_object_set_new(json_info.json_write_case, "signature", obj); 177 } else if (info.op == FIPS_TEST_ASYM_SIGVER) { 178 if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS) 179 json_object_set_new(json_info.json_write_case, "testPassed", json_true()); 180 else 181 json_object_set_new(json_info.json_write_case, "testPassed", json_false()); 182 } else if (info.op == FIPS_TEST_ASYM_KEYGEN) { 183 json_t *obj; 184 185 writeback_hex_str("", info.one_line_text, &vec.eddsa.pkey); 186 obj = json_string(info.one_line_text); 187 json_object_set_new(json_info.json_write_case, "d", obj); 188 189 writeback_hex_str("", info.one_line_text, &vec.eddsa.q); 190 obj = json_string(info.one_line_text); 191 json_object_set_new(json_info.json_write_case, "q", obj); 192 } 193 194 return 0; 195 } 196 197 static int 198 parse_interim_str(const char *key, char *src, struct fips_val *val) 199 { 200 uint32_t i; 201 202 RTE_SET_USED(val); 203 204 if (strcmp(key, TESTTYPE_JSON_STR) == 0) { 205 for (i = 0; i < RTE_DIM(eddsa_test_types); i++) 206 if (strstr(src, eddsa_test_types[i].desc)) { 207 info.parse_writeback = parse_test_eddsa_json_writeback; 208 break; 209 } 210 211 if (!info.parse_writeback || i >= RTE_DIM(eddsa_test_types)) 212 return -EINVAL; 213 214 } else if (strcmp(key, CURVE_JSON_STR) == 0) { 215 for (i = 0; i < RTE_DIM(eddsa_curve_ids); i++) 216 if (strstr(src, eddsa_curve_ids[i].desc)) { 217 info.interim_info.eddsa_data.curve_id = eddsa_curve_ids[i].curve_id; 218 info.interim_info.eddsa_data.curve_len = 219 eddsa_curve_len[i].curve_len; 220 break; 221 } 222 223 if (i >= RTE_DIM(eddsa_curve_ids)) 224 return -EINVAL; 225 } else if (strcmp(key, PH_JSON_STR) == 0) { 226 info.interim_info.eddsa_data.prehash = false; 227 } else { 228 return -EINVAL; 229 } 230 231 return 0; 232 } 233 234 static int 235 parse_keygen_tc_str(const char *key, char *src, struct fips_val *val) 236 { 237 RTE_SET_USED(key); 238 RTE_SET_USED(src); 239 RTE_SET_USED(val); 240 241 if (info.op == FIPS_TEST_ASYM_KEYGEN) { 242 if (vec.eddsa.pkey.val) { 243 rte_free(vec.eddsa.pkey.val); 244 vec.eddsa.pkey.val = NULL; 245 } 246 247 if (prepare_vec_eddsa() < 0) 248 return -1; 249 250 info.interim_info.eddsa_data.pubkey_gen = 1; 251 } 252 253 return 0; 254 } 255 256 struct fips_test_callback eddsa_interim_json_vectors[] = { 257 {TESTTYPE_JSON_STR, parse_interim_str, NULL}, 258 {CURVE_JSON_STR, parse_interim_str, NULL}, 259 {NULL, NULL, NULL} /**< end pointer */ 260 }; 261 262 struct fips_test_callback eddsa_siggen_json_vectors[] = { 263 {MSG_JSON_STR, parse_uint8_hex_str, &vec.pt}, 264 {CTX_JSON_STR, parse_uint8_hex_str, &vec.eddsa.ctx}, 265 {NULL, NULL, NULL} /**< end pointer */ 266 }; 267 268 struct fips_test_callback eddsa_sigver_json_vectors[] = { 269 {MSG_JSON_STR, parse_uint8_hex_str, &vec.pt}, 270 {Q_JSON_STR, parse_uint8_hex_str, &vec.eddsa.q}, 271 {SIG_JSON_STR, parse_uint8_hex_str, &vec.eddsa.sign}, 272 {NULL, NULL, NULL} /**< end pointer */ 273 }; 274 275 struct fips_test_callback eddsa_keygen_json_vectors[] = { 276 {"tcId", parse_keygen_tc_str, &vec.pt}, 277 {NULL, NULL, NULL} /**< end pointer */ 278 }; 279 280 int 281 parse_test_eddsa_json_init(void) 282 { 283 json_t *mode_obj = json_object_get(json_info.json_vector_set, "mode"); 284 const char *mode_str = json_string_value(mode_obj); 285 286 info.callbacks = NULL; 287 info.parse_writeback = NULL; 288 289 info.interim_callbacks = eddsa_interim_json_vectors; 290 info.post_interim_writeback = post_test_eddsa_json_interim_writeback; 291 info.parse_interim_writeback = parse_test_eddsa_json_interim_writeback; 292 if (strcmp(mode_str, "sigGen") == 0) { 293 info.op = FIPS_TEST_ASYM_SIGGEN; 294 info.callbacks = eddsa_siggen_json_vectors; 295 } else if (strcmp(mode_str, "sigVer") == 0) { 296 info.op = FIPS_TEST_ASYM_SIGVER; 297 info.callbacks = eddsa_sigver_json_vectors; 298 } else if (strcmp(mode_str, "keyGen") == 0) { 299 info.op = FIPS_TEST_ASYM_KEYGEN; 300 info.callbacks = eddsa_keygen_json_vectors; 301 } else { 302 return -EINVAL; 303 } 304 305 return 0; 306 } 307 #endif /* USE_JANSSON */ 308