112ede9acSGowrishankar Muthukrishnan /* SPDX-License-Identifier: BSD-3-Clause 212ede9acSGowrishankar Muthukrishnan * Copyright(C) 2023 Marvell. 312ede9acSGowrishankar Muthukrishnan */ 412ede9acSGowrishankar Muthukrishnan 512ede9acSGowrishankar Muthukrishnan #include <string.h> 612ede9acSGowrishankar Muthukrishnan #include <time.h> 712ede9acSGowrishankar Muthukrishnan #include <stdio.h> 812ede9acSGowrishankar Muthukrishnan #include <sys/types.h> 912ede9acSGowrishankar Muthukrishnan #include <unistd.h> 1012ede9acSGowrishankar Muthukrishnan 1112ede9acSGowrishankar Muthukrishnan #ifdef USE_OPENSSL 1212ede9acSGowrishankar Muthukrishnan #include <openssl/bn.h> 1312ede9acSGowrishankar Muthukrishnan #include <openssl/rand.h> 1412ede9acSGowrishankar Muthukrishnan #endif /* USE_OPENSSL */ 1512ede9acSGowrishankar Muthukrishnan 1612ede9acSGowrishankar Muthukrishnan #include <rte_cryptodev.h> 1712ede9acSGowrishankar Muthukrishnan #include <rte_malloc.h> 1812ede9acSGowrishankar Muthukrishnan 1912ede9acSGowrishankar Muthukrishnan #include "fips_validation.h" 2012ede9acSGowrishankar Muthukrishnan 2112ede9acSGowrishankar Muthukrishnan #define TESTTYPE_JSON_STR "testType" 2212ede9acSGowrishankar Muthukrishnan #define CURVE_JSON_STR "curve" 2312ede9acSGowrishankar Muthukrishnan #define PH_JSON_STR "preHash" 2412ede9acSGowrishankar Muthukrishnan 2512ede9acSGowrishankar Muthukrishnan #define MSG_JSON_STR "message" 2612ede9acSGowrishankar Muthukrishnan #define CTX_JSON_STR "context" 2712ede9acSGowrishankar Muthukrishnan #define Q_JSON_STR "q" 2812ede9acSGowrishankar Muthukrishnan #define SIG_JSON_STR "signature" 2912ede9acSGowrishankar Muthukrishnan 3012ede9acSGowrishankar Muthukrishnan #ifdef USE_JANSSON 3112ede9acSGowrishankar Muthukrishnan struct { 3212ede9acSGowrishankar Muthukrishnan uint8_t type; 3312ede9acSGowrishankar Muthukrishnan const char *desc; 3412ede9acSGowrishankar Muthukrishnan } eddsa_test_types[] = { 3512ede9acSGowrishankar Muthukrishnan {EDDSA_AFT, "AFT"}, 3612ede9acSGowrishankar Muthukrishnan {EDDSA_BFT, "BFT"} 3712ede9acSGowrishankar Muthukrishnan }; 3812ede9acSGowrishankar Muthukrishnan 3912ede9acSGowrishankar Muthukrishnan struct { 4012ede9acSGowrishankar Muthukrishnan enum rte_crypto_curve_id curve_id; 4112ede9acSGowrishankar Muthukrishnan const char *desc; 4212ede9acSGowrishankar Muthukrishnan } eddsa_curve_ids[] = { 4312ede9acSGowrishankar Muthukrishnan {RTE_CRYPTO_EC_GROUP_ED25519, "ED-25519"}, 4412ede9acSGowrishankar Muthukrishnan {RTE_CRYPTO_EC_GROUP_ED448, "ED-448"}, 4512ede9acSGowrishankar Muthukrishnan }; 4612ede9acSGowrishankar Muthukrishnan 4712ede9acSGowrishankar Muthukrishnan struct { 4812ede9acSGowrishankar Muthukrishnan uint8_t curve_len; 4912ede9acSGowrishankar Muthukrishnan const char *desc; 5012ede9acSGowrishankar Muthukrishnan } eddsa_curve_len[] = { 51*2cf2f844SGowrishankar Muthukrishnan {64, "ED-25519"}, 52*2cf2f844SGowrishankar Muthukrishnan {114, "ED-448"}, 5312ede9acSGowrishankar Muthukrishnan }; 5412ede9acSGowrishankar Muthukrishnan 5512ede9acSGowrishankar Muthukrishnan #ifdef USE_OPENSSL 5612ede9acSGowrishankar Muthukrishnan #define MAX_TRIES 10 5712ede9acSGowrishankar Muthukrishnan static int 5812ede9acSGowrishankar Muthukrishnan prepare_vec_eddsa(void) 5912ede9acSGowrishankar Muthukrishnan { 6012ede9acSGowrishankar Muthukrishnan BIGNUM *pkey = NULL, *order = NULL; 6112ede9acSGowrishankar Muthukrishnan int ret = -1, j; 6212ede9acSGowrishankar Muthukrishnan unsigned long pid; 6312ede9acSGowrishankar Muthukrishnan 6412ede9acSGowrishankar Muthukrishnan /* For EdDSA prime fields, order of base points (RFC 8032 Section 5.1 and 5.2). 6512ede9acSGowrishankar Muthukrishnan */ 6612ede9acSGowrishankar Muthukrishnan static const char * const orderstr[] = { 6712ede9acSGowrishankar Muthukrishnan "7237005577332262213973186563042994240857116359379907606001950938285454250989", 6812ede9acSGowrishankar Muthukrishnan "181709681073901722637330951972001133588410340171829515070372549795146003961539585716195755291692375963310293709091662304773755859649779", 6912ede9acSGowrishankar Muthukrishnan }; 7012ede9acSGowrishankar Muthukrishnan 7112ede9acSGowrishankar Muthukrishnan pid = getpid(); 7212ede9acSGowrishankar Muthukrishnan RAND_seed(&pid, sizeof(pid)); 7312ede9acSGowrishankar Muthukrishnan 7412ede9acSGowrishankar Muthukrishnan if (!RAND_status()) 7512ede9acSGowrishankar Muthukrishnan return -1; 7612ede9acSGowrishankar Muthukrishnan 7712ede9acSGowrishankar Muthukrishnan order = BN_new(); 7812ede9acSGowrishankar Muthukrishnan if (!order) 7912ede9acSGowrishankar Muthukrishnan goto err; 8012ede9acSGowrishankar Muthukrishnan 8112ede9acSGowrishankar Muthukrishnan j = info.interim_info.eddsa_data.curve_id - RTE_CRYPTO_EC_GROUP_ED25519; 8212ede9acSGowrishankar Muthukrishnan if (!BN_hex2bn(&order, orderstr[j])) 8312ede9acSGowrishankar Muthukrishnan goto err; 8412ede9acSGowrishankar Muthukrishnan 8512ede9acSGowrishankar Muthukrishnan pkey = BN_new(); 8612ede9acSGowrishankar Muthukrishnan if (!pkey) 8712ede9acSGowrishankar Muthukrishnan goto err; 8812ede9acSGowrishankar Muthukrishnan 8912ede9acSGowrishankar Muthukrishnan for (j = 0; j < MAX_TRIES; j++) { 9012ede9acSGowrishankar Muthukrishnan /* pkey should be in [1, order - 1] */ 9112ede9acSGowrishankar Muthukrishnan if (!BN_rand_range(pkey, order)) 9212ede9acSGowrishankar Muthukrishnan goto err; 9312ede9acSGowrishankar Muthukrishnan 9412ede9acSGowrishankar Muthukrishnan if (!BN_is_zero(pkey)) 9512ede9acSGowrishankar Muthukrishnan break; 9612ede9acSGowrishankar Muthukrishnan } 9712ede9acSGowrishankar Muthukrishnan 9812ede9acSGowrishankar Muthukrishnan if (j == MAX_TRIES) 9912ede9acSGowrishankar Muthukrishnan goto err; 10012ede9acSGowrishankar Muthukrishnan 10112ede9acSGowrishankar Muthukrishnan parse_uint8_hex_str("", BN_bn2hex(pkey), &vec.eddsa.pkey); 10212ede9acSGowrishankar Muthukrishnan 10312ede9acSGowrishankar Muthukrishnan ret = 0; 10412ede9acSGowrishankar Muthukrishnan err: 10512ede9acSGowrishankar Muthukrishnan BN_free(order); 10612ede9acSGowrishankar Muthukrishnan BN_free(pkey); 10712ede9acSGowrishankar Muthukrishnan return ret; 10812ede9acSGowrishankar Muthukrishnan } 10912ede9acSGowrishankar Muthukrishnan #else 11012ede9acSGowrishankar Muthukrishnan static int 11112ede9acSGowrishankar Muthukrishnan prepare_vec_eddsa(void) 11212ede9acSGowrishankar Muthukrishnan { 11312ede9acSGowrishankar Muthukrishnan /* 11412ede9acSGowrishankar Muthukrishnan * Generate EdDSA values. 11512ede9acSGowrishankar Muthukrishnan */ 11612ede9acSGowrishankar Muthukrishnan return -ENOTSUP; 11712ede9acSGowrishankar Muthukrishnan } 11812ede9acSGowrishankar Muthukrishnan #endif /* USE_OPENSSL */ 11912ede9acSGowrishankar Muthukrishnan 12012ede9acSGowrishankar Muthukrishnan static int 12112ede9acSGowrishankar Muthukrishnan parse_test_eddsa_json_interim_writeback(struct fips_val *val) 12212ede9acSGowrishankar Muthukrishnan { 12312ede9acSGowrishankar Muthukrishnan RTE_SET_USED(val); 12412ede9acSGowrishankar Muthukrishnan 12512ede9acSGowrishankar Muthukrishnan if (info.op == FIPS_TEST_ASYM_SIGGEN) { 12612ede9acSGowrishankar Muthukrishnan /* For siggen tests, EdDSA values can be created soon after 12712ede9acSGowrishankar Muthukrishnan * the test group data are parsed. 12812ede9acSGowrishankar Muthukrishnan */ 12912ede9acSGowrishankar Muthukrishnan if (vec.eddsa.pkey.val) { 13012ede9acSGowrishankar Muthukrishnan rte_free(vec.eddsa.pkey.val); 13112ede9acSGowrishankar Muthukrishnan vec.eddsa.pkey.val = NULL; 13212ede9acSGowrishankar Muthukrishnan } 13312ede9acSGowrishankar Muthukrishnan 13412ede9acSGowrishankar Muthukrishnan if (prepare_vec_eddsa() < 0) 13512ede9acSGowrishankar Muthukrishnan return -1; 13612ede9acSGowrishankar Muthukrishnan 13712ede9acSGowrishankar Muthukrishnan info.interim_info.eddsa_data.pubkey_gen = 1; 13812ede9acSGowrishankar Muthukrishnan } 13912ede9acSGowrishankar Muthukrishnan 14012ede9acSGowrishankar Muthukrishnan return 0; 14112ede9acSGowrishankar Muthukrishnan } 14212ede9acSGowrishankar Muthukrishnan 14312ede9acSGowrishankar Muthukrishnan static int 14412ede9acSGowrishankar Muthukrishnan post_test_eddsa_json_interim_writeback(struct fips_val *val) 14512ede9acSGowrishankar Muthukrishnan { 14612ede9acSGowrishankar Muthukrishnan RTE_SET_USED(val); 14712ede9acSGowrishankar Muthukrishnan 14812ede9acSGowrishankar Muthukrishnan if (info.op == FIPS_TEST_ASYM_KEYGEN) { 14912ede9acSGowrishankar Muthukrishnan json_t *obj; 15012ede9acSGowrishankar Muthukrishnan 15112ede9acSGowrishankar Muthukrishnan writeback_hex_str("", info.one_line_text, &vec.eddsa.q); 15212ede9acSGowrishankar Muthukrishnan obj = json_string(info.one_line_text); 15312ede9acSGowrishankar Muthukrishnan json_object_set_new(json_info.json_write_group, "q", obj); 15412ede9acSGowrishankar Muthukrishnan } 15512ede9acSGowrishankar Muthukrishnan 15612ede9acSGowrishankar Muthukrishnan return 0; 15712ede9acSGowrishankar Muthukrishnan } 15812ede9acSGowrishankar Muthukrishnan 15912ede9acSGowrishankar Muthukrishnan static int 16012ede9acSGowrishankar Muthukrishnan parse_test_eddsa_json_writeback(struct fips_val *val) 16112ede9acSGowrishankar Muthukrishnan { 16212ede9acSGowrishankar Muthukrishnan json_t *tcId; 16312ede9acSGowrishankar Muthukrishnan 16412ede9acSGowrishankar Muthukrishnan RTE_SET_USED(val); 16512ede9acSGowrishankar Muthukrishnan 16612ede9acSGowrishankar Muthukrishnan tcId = json_object_get(json_info.json_test_case, "tcId"); 16712ede9acSGowrishankar Muthukrishnan 16812ede9acSGowrishankar Muthukrishnan json_info.json_write_case = json_object(); 16912ede9acSGowrishankar Muthukrishnan json_object_set(json_info.json_write_case, "tcId", tcId); 17012ede9acSGowrishankar Muthukrishnan 17112ede9acSGowrishankar Muthukrishnan if (info.op == FIPS_TEST_ASYM_SIGGEN) { 17212ede9acSGowrishankar Muthukrishnan json_t *obj; 17312ede9acSGowrishankar Muthukrishnan 17412ede9acSGowrishankar Muthukrishnan writeback_hex_str("", info.one_line_text, &vec.eddsa.sign); 17512ede9acSGowrishankar Muthukrishnan obj = json_string(info.one_line_text); 17612ede9acSGowrishankar Muthukrishnan json_object_set_new(json_info.json_write_case, "signature", obj); 17712ede9acSGowrishankar Muthukrishnan } else if (info.op == FIPS_TEST_ASYM_SIGVER) { 17812ede9acSGowrishankar Muthukrishnan if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS) 17912ede9acSGowrishankar Muthukrishnan json_object_set_new(json_info.json_write_case, "testPassed", json_true()); 18012ede9acSGowrishankar Muthukrishnan else 18112ede9acSGowrishankar Muthukrishnan json_object_set_new(json_info.json_write_case, "testPassed", json_false()); 18212ede9acSGowrishankar Muthukrishnan } else if (info.op == FIPS_TEST_ASYM_KEYGEN) { 18312ede9acSGowrishankar Muthukrishnan json_t *obj; 18412ede9acSGowrishankar Muthukrishnan 18512ede9acSGowrishankar Muthukrishnan writeback_hex_str("", info.one_line_text, &vec.eddsa.pkey); 18612ede9acSGowrishankar Muthukrishnan obj = json_string(info.one_line_text); 18712ede9acSGowrishankar Muthukrishnan json_object_set_new(json_info.json_write_case, "d", obj); 18812ede9acSGowrishankar Muthukrishnan 18912ede9acSGowrishankar Muthukrishnan writeback_hex_str("", info.one_line_text, &vec.eddsa.q); 19012ede9acSGowrishankar Muthukrishnan obj = json_string(info.one_line_text); 19112ede9acSGowrishankar Muthukrishnan json_object_set_new(json_info.json_write_case, "q", obj); 19212ede9acSGowrishankar Muthukrishnan } 19312ede9acSGowrishankar Muthukrishnan 19412ede9acSGowrishankar Muthukrishnan return 0; 19512ede9acSGowrishankar Muthukrishnan } 19612ede9acSGowrishankar Muthukrishnan 19712ede9acSGowrishankar Muthukrishnan static int 19812ede9acSGowrishankar Muthukrishnan parse_interim_str(const char *key, char *src, struct fips_val *val) 19912ede9acSGowrishankar Muthukrishnan { 20012ede9acSGowrishankar Muthukrishnan uint32_t i; 20112ede9acSGowrishankar Muthukrishnan 20212ede9acSGowrishankar Muthukrishnan RTE_SET_USED(val); 20312ede9acSGowrishankar Muthukrishnan 20412ede9acSGowrishankar Muthukrishnan if (strcmp(key, TESTTYPE_JSON_STR) == 0) { 20512ede9acSGowrishankar Muthukrishnan for (i = 0; i < RTE_DIM(eddsa_test_types); i++) 20612ede9acSGowrishankar Muthukrishnan if (strstr(src, eddsa_test_types[i].desc)) { 20712ede9acSGowrishankar Muthukrishnan info.parse_writeback = parse_test_eddsa_json_writeback; 20812ede9acSGowrishankar Muthukrishnan break; 20912ede9acSGowrishankar Muthukrishnan } 21012ede9acSGowrishankar Muthukrishnan 21112ede9acSGowrishankar Muthukrishnan if (!info.parse_writeback || i >= RTE_DIM(eddsa_test_types)) 21212ede9acSGowrishankar Muthukrishnan return -EINVAL; 21312ede9acSGowrishankar Muthukrishnan 21412ede9acSGowrishankar Muthukrishnan } else if (strcmp(key, CURVE_JSON_STR) == 0) { 21512ede9acSGowrishankar Muthukrishnan for (i = 0; i < RTE_DIM(eddsa_curve_ids); i++) 21612ede9acSGowrishankar Muthukrishnan if (strstr(src, eddsa_curve_ids[i].desc)) { 21712ede9acSGowrishankar Muthukrishnan info.interim_info.eddsa_data.curve_id = eddsa_curve_ids[i].curve_id; 21812ede9acSGowrishankar Muthukrishnan info.interim_info.eddsa_data.curve_len = 21912ede9acSGowrishankar Muthukrishnan eddsa_curve_len[i].curve_len; 22012ede9acSGowrishankar Muthukrishnan break; 22112ede9acSGowrishankar Muthukrishnan } 22212ede9acSGowrishankar Muthukrishnan 22312ede9acSGowrishankar Muthukrishnan if (i >= RTE_DIM(eddsa_curve_ids)) 22412ede9acSGowrishankar Muthukrishnan return -EINVAL; 22512ede9acSGowrishankar Muthukrishnan } else if (strcmp(key, PH_JSON_STR) == 0) { 22612ede9acSGowrishankar Muthukrishnan info.interim_info.eddsa_data.prehash = false; 22712ede9acSGowrishankar Muthukrishnan } else { 22812ede9acSGowrishankar Muthukrishnan return -EINVAL; 22912ede9acSGowrishankar Muthukrishnan } 23012ede9acSGowrishankar Muthukrishnan 23112ede9acSGowrishankar Muthukrishnan return 0; 23212ede9acSGowrishankar Muthukrishnan } 23312ede9acSGowrishankar Muthukrishnan 23412ede9acSGowrishankar Muthukrishnan static int 23512ede9acSGowrishankar Muthukrishnan parse_keygen_tc_str(const char *key, char *src, struct fips_val *val) 23612ede9acSGowrishankar Muthukrishnan { 23712ede9acSGowrishankar Muthukrishnan RTE_SET_USED(key); 23812ede9acSGowrishankar Muthukrishnan RTE_SET_USED(src); 23912ede9acSGowrishankar Muthukrishnan RTE_SET_USED(val); 24012ede9acSGowrishankar Muthukrishnan 24112ede9acSGowrishankar Muthukrishnan if (info.op == FIPS_TEST_ASYM_KEYGEN) { 24212ede9acSGowrishankar Muthukrishnan if (vec.eddsa.pkey.val) { 24312ede9acSGowrishankar Muthukrishnan rte_free(vec.eddsa.pkey.val); 24412ede9acSGowrishankar Muthukrishnan vec.eddsa.pkey.val = NULL; 24512ede9acSGowrishankar Muthukrishnan } 24612ede9acSGowrishankar Muthukrishnan 24712ede9acSGowrishankar Muthukrishnan if (prepare_vec_eddsa() < 0) 24812ede9acSGowrishankar Muthukrishnan return -1; 24912ede9acSGowrishankar Muthukrishnan 25012ede9acSGowrishankar Muthukrishnan info.interim_info.eddsa_data.pubkey_gen = 1; 25112ede9acSGowrishankar Muthukrishnan } 25212ede9acSGowrishankar Muthukrishnan 25312ede9acSGowrishankar Muthukrishnan return 0; 25412ede9acSGowrishankar Muthukrishnan } 25512ede9acSGowrishankar Muthukrishnan 25612ede9acSGowrishankar Muthukrishnan struct fips_test_callback eddsa_interim_json_vectors[] = { 25712ede9acSGowrishankar Muthukrishnan {TESTTYPE_JSON_STR, parse_interim_str, NULL}, 25812ede9acSGowrishankar Muthukrishnan {CURVE_JSON_STR, parse_interim_str, NULL}, 25912ede9acSGowrishankar Muthukrishnan {NULL, NULL, NULL} /**< end pointer */ 26012ede9acSGowrishankar Muthukrishnan }; 26112ede9acSGowrishankar Muthukrishnan 26212ede9acSGowrishankar Muthukrishnan struct fips_test_callback eddsa_siggen_json_vectors[] = { 26312ede9acSGowrishankar Muthukrishnan {MSG_JSON_STR, parse_uint8_hex_str, &vec.pt}, 26412ede9acSGowrishankar Muthukrishnan {CTX_JSON_STR, parse_uint8_hex_str, &vec.eddsa.ctx}, 26512ede9acSGowrishankar Muthukrishnan {NULL, NULL, NULL} /**< end pointer */ 26612ede9acSGowrishankar Muthukrishnan }; 26712ede9acSGowrishankar Muthukrishnan 26812ede9acSGowrishankar Muthukrishnan struct fips_test_callback eddsa_sigver_json_vectors[] = { 26912ede9acSGowrishankar Muthukrishnan {MSG_JSON_STR, parse_uint8_hex_str, &vec.pt}, 27012ede9acSGowrishankar Muthukrishnan {Q_JSON_STR, parse_uint8_hex_str, &vec.eddsa.q}, 27112ede9acSGowrishankar Muthukrishnan {SIG_JSON_STR, parse_uint8_hex_str, &vec.eddsa.sign}, 27212ede9acSGowrishankar Muthukrishnan {NULL, NULL, NULL} /**< end pointer */ 27312ede9acSGowrishankar Muthukrishnan }; 27412ede9acSGowrishankar Muthukrishnan 27512ede9acSGowrishankar Muthukrishnan struct fips_test_callback eddsa_keygen_json_vectors[] = { 27612ede9acSGowrishankar Muthukrishnan {"tcId", parse_keygen_tc_str, &vec.pt}, 27712ede9acSGowrishankar Muthukrishnan {NULL, NULL, NULL} /**< end pointer */ 27812ede9acSGowrishankar Muthukrishnan }; 27912ede9acSGowrishankar Muthukrishnan 28012ede9acSGowrishankar Muthukrishnan int 28112ede9acSGowrishankar Muthukrishnan parse_test_eddsa_json_init(void) 28212ede9acSGowrishankar Muthukrishnan { 28312ede9acSGowrishankar Muthukrishnan json_t *mode_obj = json_object_get(json_info.json_vector_set, "mode"); 28412ede9acSGowrishankar Muthukrishnan const char *mode_str = json_string_value(mode_obj); 28512ede9acSGowrishankar Muthukrishnan 28612ede9acSGowrishankar Muthukrishnan info.callbacks = NULL; 28712ede9acSGowrishankar Muthukrishnan info.parse_writeback = NULL; 28812ede9acSGowrishankar Muthukrishnan 28912ede9acSGowrishankar Muthukrishnan info.interim_callbacks = eddsa_interim_json_vectors; 29012ede9acSGowrishankar Muthukrishnan info.post_interim_writeback = post_test_eddsa_json_interim_writeback; 29112ede9acSGowrishankar Muthukrishnan info.parse_interim_writeback = parse_test_eddsa_json_interim_writeback; 29212ede9acSGowrishankar Muthukrishnan if (strcmp(mode_str, "sigGen") == 0) { 29312ede9acSGowrishankar Muthukrishnan info.op = FIPS_TEST_ASYM_SIGGEN; 29412ede9acSGowrishankar Muthukrishnan info.callbacks = eddsa_siggen_json_vectors; 29512ede9acSGowrishankar Muthukrishnan } else if (strcmp(mode_str, "sigVer") == 0) { 29612ede9acSGowrishankar Muthukrishnan info.op = FIPS_TEST_ASYM_SIGVER; 29712ede9acSGowrishankar Muthukrishnan info.callbacks = eddsa_sigver_json_vectors; 29812ede9acSGowrishankar Muthukrishnan } else if (strcmp(mode_str, "keyGen") == 0) { 29912ede9acSGowrishankar Muthukrishnan info.op = FIPS_TEST_ASYM_KEYGEN; 30012ede9acSGowrishankar Muthukrishnan info.callbacks = eddsa_keygen_json_vectors; 30112ede9acSGowrishankar Muthukrishnan } else { 30212ede9acSGowrishankar Muthukrishnan return -EINVAL; 30312ede9acSGowrishankar Muthukrishnan } 30412ede9acSGowrishankar Muthukrishnan 30512ede9acSGowrishankar Muthukrishnan return 0; 30612ede9acSGowrishankar Muthukrishnan } 30712ede9acSGowrishankar Muthukrishnan #endif /* USE_JANSSON */ 308