/* Copyright (c) (2011,2012,2014,2015,2018-2020) Apple Inc. All rights reserved. * * corecrypto is licensed under Apple Inc.’s Internal Use License Agreement (which * is contained in the License.txt file distributed with corecrypto) and only to * people who accept that license. IMPORTANT: Any license rights granted to you by * Apple Inc. (if any) are limited to internal use within your organization only on * devices and computers you own or control, for the sole purpose of verifying the * security characteristics and correct functioning of the Apple Software. You may * not, directly or indirectly, redistribute the Apple Software or any portions thereof. */ #import "CCZKATValidation.h" #import "ccz_unit.h" #import "ccn_unit.h" #import "string.h" #import struct test_alloc_context { unsigned test_allocs, test_frees, test_reallocs; } gtac; static void * test_ccz_alloc(void *ctx, size_t size) { struct test_alloc_context *tac = ctx; tac->test_allocs++; return malloc(size); } static void test_ccz_free(void *ctx, size_t oldsize, void *p) { struct test_alloc_context *tac = ctx; tac->test_frees++; cc_clear(oldsize, p); free(p); } static void * test_ccz_realloc(void *ctx, size_t oldsize, void *p, size_t newsize) { struct test_alloc_context *tac = ctx; tac->test_reallocs++; void *r = malloc(newsize); memcpy(r, p, oldsize); cc_clear(oldsize, p); free(p); return r; } struct ccz_class test_ccz_isa = { .ctx = >ac, .ccz_alloc = test_ccz_alloc, .ccz_realloc = test_ccz_realloc, .ccz_free = test_ccz_free }; static const uint8_t abytes[192/8] = { 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x20,0x21,0x22,0x23,0x24 }; static cc_unit a192[ccn_nof(192)] = { CCN192_C(01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24)}; static cc_unit b192[ccn_nof(192)] = { CCN192_C(24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,09,08,07,06,05,04,03,02,01)}; static cc_unit c192[ccn_nof(192)] = { CCN192_C(00,00,00,00,00,00,17,16,15,14,13,12,11,10,09,00,00,00,00,00,00,00,00,00)}; static cc_unit lsr192a[ccn_nof(192)] = { CCN192_C(00,81,01,82,02,83,03,84,04,88,08,89,09,8A,0A,8B,0B,8C,0C,90,10,91,11,92)}; static cc_unit lsr192a8[ccn_nof(192)] = { CCN192_C(00,01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23)}; static cc_unit lsr192a64[ccn_nof(192)] = { CCN192_C(00,00,00,00,00,00,00,00,01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16)}; static cc_unit lsr192a65[ccn_nof(192)] = { CCN192_C(00,00,00,00,00,00,00,00,00,81,01,82,02,83,03,84,04,88,08,89,09,8A,0A,8B)}; static cc_unit lsl192a[ccn_nof(192)] = { CCN192_C(02,04,06,08,0A,0C,0E,10,12,20,22,24,26,28,2A,2C,2E,30,32,40,42,44,46,48)}; static cc_unit lsl256a64[ccn_nof(256)] = { CCN256_C(01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,00,00,00,00,00,00,00,00)}; static cc_unit lsl256a65[ccn_nof(256)] = { CCN256_C(02,04,06,08,0A,0C,0E,10,12,20,22,24,26,28,2A,2C,2E,30,32,40,42,44,46,48,00,00,00,00,00,00,00,00)}; static cc_unit sum192ab[ccn_nof(192)] = { CCN192_C(25,25,25,25,25,1f,1f,1f,1f,25,25,25,25,25,25,1f,1f,1f,1f,25,25,25,25,25)}; static cc_unit diff192ba[ccn_nof(192)] = { CCN192_C(23,21,1f,1d,1b,13,11,0f,0d,05,03,00,fe,fc,fa,f2,f0,ee,ec,e4,e2,e0,de,dd)}; static cc_unit prod384ab[ccn_nof(384)] = { CCN384_C(00,24,6b,d5,60,0a,ce,aa,9d,a7,9e,a3,b5,d3,fd,0c,1e,32,47,5d,4a,2f,0a,dc,9d,d7,05,29,44,58,43,2e,1a,07,f8,cf,b1,9f,9a,a4,9b,a8,cd,09,5e,d4,6b,24)}; static cc_unit square384a[ccn_nof(384)] = { CCN384_C(00,01,04,0a,14,23,38,54,78,a5,e9,43,b6,41,e7,a8,85,7f,97,f3,7b,30,13,25,67,90,9f,93,6b,6e,53,18,be,40,e5,5a,9f,b3,95,68,06,6f,a2,9c,a2,62,dd,10)}; @implementation CCZKATValidation - (void) setUp { a = malloc(ccz_size(&test_ccz_isa)); b = malloc(ccz_size(&test_ccz_isa)); c = malloc(ccz_size(&test_ccz_isa)); d = malloc(ccz_size(&test_ccz_isa)); r = malloc(ccz_size(&test_ccz_isa)); ccz_init(&test_ccz_isa, a); ccz_init(&test_ccz_isa, b); ccz_init(&test_ccz_isa, c); ccz_init(&test_ccz_isa, d); ccz_init(&test_ccz_isa, r); a_c.n = ccn_n(ccn_nof(192), a192); a_c.u = a192; b_c.n = ccn_n(ccn_nof(192), b192); b_c.u = b192; c_c.n = ccn_n(ccn_nof(192), c192); c_c.u = c192; lsra_c.n = ccn_n(ccn_nof(192), lsr192a); lsra_c.u = lsr192a; lsra8_c.n = ccn_n(ccn_nof(192), lsr192a8); lsra8_c.u = lsr192a8; lsra64_c.n = ccn_n(ccn_nof(192), lsr192a64); lsra64_c.u = lsr192a64; lsra65_c.n = ccn_n(ccn_nof(192), lsr192a65); lsra65_c.u = lsr192a65; lsla_c.n = ccn_n(ccn_nof(192), lsl192a); lsla_c.u = lsl192a; lsla64_c.n = ccn_n(ccn_nof(256), lsl256a64); lsla64_c.u = lsl256a64; lsla65_c.n = ccn_n(ccn_nof(256), lsl256a65); lsla65_c.u = lsl256a65; sumab_c.n = ccn_n(ccn_nof(192), sum192ab); sumab_c.u = sum192ab; diffba_c.n = ccn_n(ccn_nof(192), diff192ba); diffba_c.u = diff192ba; prodab_c.n = ccn_n(ccn_nof(384), prod384ab); prodab_c.u = prod384ab; squarea_c.n = ccn_n(ccn_nof(384), square384a); squarea_c.u = square384a; cc_clear(sizeof(gtac), >ac); expected_reallocs = 0; } - (void) tearDown { ccz_free(r); ccz_free(d); ccz_free(c); ccz_free(b); ccz_free(a); free(r); free(d); free(c); free(b); free(a); XCTAssertEqual(gtac.test_allocs, gtac.test_frees, @"allocs == frees"); XCTAssertEqual(gtac.test_reallocs, expected_reallocs, @"reallocs == 0"); } - (void)test_bit { XCTAssertEqual(ccz_bit(&a_c, 0), (bool)0, @"bit 0 of a192 is 0."); XCTAssertEqual(ccz_bit(&a_c, 2), (bool)1, @"bit 2 of a192 is 1."); XCTAssertEqual(ccz_bit(&b_c, 0), (bool)1, @"bit 0 of b192 is 1."); XCTAssertEqual(ccz_bit(&b_c, 191), (bool)0, @"bit 191 of b192 is 0."); XCTAssertEqual(ccz_bit(&b_c, 189), (bool)1, @"bit 189 of b192 is 1."); } - (void)test_set_bit { ccz_zero(a); for (size_t bit = 0; bit < 128; ++bit) { XCTAssertEqual(ccz_bit(a, bit), (bool)0, @"bit %zu of a is 0.", bit); ccz_set_bit(a, bit, 1); XCTAssertEqual(ccz_bit(a, bit), (bool)1, @"bit %zu of a is now 1.", bit); ccz_set_bit(a, bit, 0); XCTAssertEqual(ccz_bit(a, bit), (bool)0, @"bit %zu of a is now 0 again.", bit); } } - (void)test_lsr { ccz_lsr(r, &a_c, 1); XCAssertCCZEquals(r, &lsra_c, @"ccz_lsr(r, a_c, 1) works"); ccz_set(r, &a_c); ccz_lsr(r, r, 1); XCAssertCCZEquals(r, &lsra_c, @"ccz_lsr(r, r, 1) works"); ccz_lsr(r, &a_c, 8); XCAssertCCZEquals(r, &lsra8_c, @"ccz_lsr(r, a_c, 8) works"); ccz_set(r, &a_c); ccz_lsr(r, r, 8); XCAssertCCZEquals(r, &lsra8_c, @"ccz_lsr(r, r, 8) works"); ccz_lsr(r, &a_c, 64); XCAssertCCZEquals(r, &lsra64_c, @"ccz_lsr(r, a_c, 64) works"); ccz_set(r, &a_c); ccz_lsr(r, r, 64); XCAssertCCZEquals(r, &lsra64_c, @"ccz_lsr(r, r, 64) works"); ccz_lsr(r, &a_c, 65); XCAssertCCZEquals(r, &lsra65_c, @"ccz_lsr(r, a_c, 65) works"); ccz_set(r, &a_c); ccz_lsr(r, r, 65); XCAssertCCZEquals(r, &lsra65_c, @"ccz_lsr(r, r, 65) works"); } - (void)test_lsl { ccz_lsl(r, &a_c, 1); XCAssertCCZEquals(r, &lsla_c, @"ccz_lsl(r, a_c, 1) works"); ccz_set(r, &a_c); ccz_lsl(r, r, 1); XCAssertCCZEquals(r, &lsla_c, @"ccz_lsl(r, r, 1) works"); ccz_lsl(r, &a_c, 64); XCAssertCCZEquals(r, &lsla64_c, @"ccz_lsl(r, a_c, 64) works"); ccz_set(r, &a_c); ccz_lsl(r, r, 64); XCAssertCCZEquals(r, &lsla64_c, @"ccz_lsl(r, r, 64) works"); ccz_lsl(r, &a_c, 65); XCAssertCCZEquals(r, &lsla65_c, @"ccz_lsl(r, a_c, 65) works"); ccz_set(r, &a_c); ccz_lsl(r, r, 65); XCAssertCCZEquals(r, &lsla65_c, @"ccz_lsl(r, r, 65) works"); } - (void)test_bitlen { XCTAssertEqual(ccz_bitlen(&a_c), (size_t)185, @"ccz_bitlen(r, a_c) works"); XCTAssertEqual(ccz_bitlen(&b_c), (size_t)190, @"ccz_bitlen(r, b_c) works"); XCTAssertEqual(ccz_bitlen(&c_c), (size_t)141, @"ccz_bitlen(r, c_c) works"); } - (void)test_trailing_zeros { XCTAssertEqual(ccz_trailing_zeros(&a_c), (size_t)2, @"ccz_trailing_zeros(r, a_c) works"); XCTAssertEqual(ccz_trailing_zeros(&b_c), (size_t)0, @"ccz_trailing_zeros(r, b_c) works"); XCTAssertEqual(ccz_trailing_zeros(&c_c), (size_t)72, @"ccz_trailing_zeros(r, c_c) works"); } - (void)test_is_zero { ccz_zero(r); XCTAssertEqual(ccz_is_zero(&a_c), (bool)false, @"ccz_is_zero(r, a_c) works"); XCTAssertEqual(ccz_is_zero(r), (bool)true, @"ccz_is_zero(r, 0) works"); } - (void)test_is_one { ccz_zero(r); XCTAssertEqual(ccz_is_one(&a_c), (bool)false, @"ccz_is_one(r, a_c) works"); XCTAssertEqual(ccz_is_one(r), (bool)false, @"ccz_is_one(r, 0) works"); ccz_seti(r, 1); XCTAssertEqual(ccz_is_one(r), (bool)true, @"ccz_is_one(r, 1) works"); } - (void)test_basic { ccz_zero(a); XCTAssertEqual(ccz_is_zero(a), (bool)true, @"freshly initialized ccz is_zero"); ccz_seti(b, 42); XCTAssertEqual(ccz_is_zero(b), (bool)false, @"42 not is_zero"); XCTAssertEqual(ccz_is_negative(a), (bool)false, @"freshly initialized ccz is not negative"); ccz_seti(c, 5047); ccz_neg(c); XCTAssertEqual(ccz_is_negative(c), (bool)true, @"-5047 is negative"); XCTAssertEqual(ccz_is_one(a), (bool)false, @"freshly initialized ccz not is_one"); XCTAssertEqual(ccz_is_one(b), (bool)false, @"42 not is_one"); XCTAssertEqual(ccz_is_one(c), (bool)false, @"-5047 not is_one"); ccz_seti(d, 1); XCTAssertEqual(ccz_is_one(d), (bool)true, @"1 is_one"); } - (void)test_cmp { XCTAssertEqual(ccz_cmp(&a_c, &a_c), 0, @"ccz_cmp(r,a_c,a_c)"); XCTAssertEqual(ccz_cmp(&a_c, &b_c), -1, @"ccz_cmp(r,a_c,b_c)"); XCTAssertEqual(ccz_cmp(&b_c, &a_c), 1, @"ccz_cmp(r,b_c,a_c)"); } // All code under test must be linked into the Unit Test bundle - (void)test_sub { ccz_sub(r, &b_c, &a_c); XCAssertCCZEquals(r, &diffba_c, @"ccz_sub(r,b_c,a_c) works"); ccz_sub(r, &a_c, &b_c); XCTAssertEqual(ccz_is_negative(r), (bool)true, @"a - b is negative"); ccz_add(r, r, &b_c); XCAssertCCZEquals(r, &a_c, @"a_c - b_c + b_c = a_c"); ccz_set(r, &b_c); ccz_sub(r, r, &a_c); XCAssertCCZEquals(r, &diffba_c, @"ccz_sub(r,r,a_c) works"); ccz_set(r, &a_c); ccz_sub(r, &b_c, r); XCAssertCCZEquals(r, &diffba_c, @"ccz_sub(r,b_c,r) works"); ccz_set(r, &a_c); ccz_sub(r, r, r); XCTAssertTrue(ccz_is_zero(r), @"after ccz_sub(r,r,r) r = 0"); } #if 0 - (void)test_sub1 { cc_unit r[ccz_nof(_c)] = {}, s[ccz_nof(_c)] = {}, t[ccz_nof(_c)] = {}; s[0] = a_c[0]; XCAssertEquals(ccz_sub(ccz_nof(_c), t, r, s), (cc_unit)1, @"r = 0, ccz_sub(r,r,a_c[0]) borrow"); XCAssertEquals(ccz_sub1(r, r, &a_c[0]), (cc_unit)1, @"r = 0, ccz_sub1(r,r,a_c[0]) borrow"); XCAssertCCZEquals(r, t, @"ccz_sub(r,b_c,r) works"); XCAssertEquals(ccz_sub1(r, &b_c, &a_c[0]), (cc_unit)0, @"ccz_sub1(r,b_c,a_c[0]) no borrow"); } #endif // All code under test must be linked into the Unit Test bundle - (void)test_add { ccz_add(r, &a_c, &b_c); XCAssertCCZEquals(r, &sumab_c, @"ccz_add(r,a,b) works"); ccz_set(r, &a_c); ccz_add(r, r, &b_c); XCAssertCCZEquals(r, &sumab_c, @"ccz_add(r,r,b) works"); ccz_set(r, &b_c); ccz_add(r, &a_c, r); XCAssertCCZEquals(r, &sumab_c, @"ccz_add(r,a,r) works"); ccz_set(r, &b_c); ccz_add(r, &a_c, r); XCAssertCCZEquals(r, &sumab_c, @"ccz_add(r,a,r) works"); ccz_set(r, &a_c); ccz_add(r, r, r); ccz_lsl(a, &a_c, 1); //XCAssertCCZEquals(a, r, @"ccz_add(r,r,r) yields same result as ccz_lsl(r, r, 1)"); } #if 0 - (void)test_add1 { cc_unit r[ccz_nof(_c)] = {}, s[ccz_nof(_c)] = {}, t[ccz_nof(_c)] = {}; s[0] = a_c[0]; XCAssertEquals(ccz_add(ccz_nof(_c), t, &b_c, s), (cc_unit)0, @"r = 0, ccz_add(r,r,a_c[0]) no carry"); XCAssertEquals(ccz_add1(r, &b_c, &a_c[0]), (cc_unit)0, @"r = 0, ccz_add1(r,r,a_c[0]) no carry"); XCAssertCCZEquals(r, t, @"ccz_add(r,b_c,r) works"); cc_unit max[1]; max[0] = ~CC_UNIT_C(0); XCAssertEquals(ccz_add1(1, r, max, CC_UNIT_C(1)), (cc_unit)1, @"r = 0, ccz_add1(r,~0,1) carry"); } #endif // All code under test must be linked into the Unit Test bundle - (void)test_mul { ccz_mul(r, &a_c, &b_c); XCAssertCCZEquals(r, &prodab_c, @"ccz_mul(r,a_c,b_c) works"); #if 0 ccz_div(r, r, &b_c); XCAssertCCZEquals(r, &a_c, @"a_c * b_c / b_c = a_c"); #endif ccz_set(r, &a_c); ccz_mul(r, r, &b_c); XCAssertCCZEquals(r, &prodab_c, @"r=a_c, ccz_mul(r,r,b_c) works"); ccz_set(r, &b_c); ccz_mul(r, &a_c, r); XCAssertCCZEquals(r, &prodab_c, @"r=b_c, ccz_mul(r,a_c,r) works"); ccz_mul(r, &a_c, &a_c); XCAssertCCZEquals(r, &squarea_c, @"ccz_mul(r,a_c,a_c) r = a_c^2"); ccz_set(r, &a_c); ccz_mul(r, r, r); XCAssertCCZEquals(r, &squarea_c, @"r=a_c, ccz_mul(r,r,r) r = a_c^2"); //making sure the swap in ccz_mul() works, when size of a and b are not equal ccz_readstr(a, "c968e40c5304364b057425920b18cc358f254ddb0f42f84850d6deec46006b4a692e52b7c3bddead45f77f2c1be1" "c606521d8a24260429f362d65b57873dbf270e97e210b872e45e97cb4cd87977ad20491e53c48cf0e88da9a61312" "675a2527c86ac537740c5e4206972f09c0f91fa1c9f14a2cf1be07e82a3b6fd58dc12c3a", 16); ccz_readstr(b,"d94a0fede757d782b54ddcf6fe8d714870b78b0e67a9754cb03a5cf63bbda1c71791902ea4527fb0cd76437391e542" "2c704ffb6d6018261171d8cee98adcf0243f1fd520fb3761afe94a2f4d99f94", 16); ccz_readstr(r,"aaf42e28af692b7defeb473a1ef2d52ce90c3fa7f19e10212b22710ba3256fea16221e5a0e553c54ba5f03bff97220" "c9b74904e52ec1731cec00cb569e86816e2c415828bd745ebff3674ea63b7a2207b96745689ba8ebf7cbd67a39fec5" "a44c613e4ac197550b9cfeb3fcb97b274b6fbf04972627434b1ed50ec4c630d39359675a63921f9fd1fdfa6db57bd4" "b13304ac0ac84d64c262d5802a1363ee1d519f88b8ca0997a77f7ece081042d88814da526c44f1323c7ac5b7eeedcc" "da0e28bc65bc415bba767d34f161ab34f9788", 16); ccz_mul(d, a,b); XCAssertCCZEquals(d, r,@"ccz_mul(r,a,b) works"); ccz_mul(d, b,a); XCAssertCCZEquals(d, r,@"ccz_mul(r,b,a) works"); } - (void)test_read_uint { ccz_read_uint(r, 192 / 8, abytes); XCAssertCCZEquals(r, &a_c, @"ccz_read_uint(a)"); } - (void)test_write_uint_size { XCTAssertEqual(ccz_write_uint_size(&a_c), (size_t)(192 / 8), @"ccz_write_uint_size(a_c) == 192/8"); } - (void)test_write_uint { size_t i_size = ccz_write_uint_size(&a_c); uint8_t bytes[i_size]; ccz_write_uint(&a_c, i_size, bytes); XCAssertMemEquals(i_size, bytes, abytes, @"ccz_write_uint(a_c)"); } - (void)test_write_uint_padded { static const uint8_t zeros[43] = {}; size_t i_size = ccz_write_uint_size(&a_c); uint8_t bytes[i_size + 43]; ccz_write_uint(&a_c, i_size + 43, bytes); XCAssertMemEquals(i_size, bytes + 43, abytes, @"ccz_write_uint_padded(a_c)"); XCAssertMemEquals(43, bytes, zeros, @"ccz_write_uint_padded(a_c)"); } - (void)test_write_int_size { XCTAssertEqual(ccz_write_int_size(&a_c), (size_t)(192 / 8), @"ccz_write_int_size(a_c) == 192/8"); ccz_set(r, &a_c); ccz_set_bit(r, 191, 1); XCTAssertEqual(ccz_write_int_size(r), (size_t)(192 / 8) + 1, @"ccz_write_int_size(0x80 a_c) == 192/8 + 1"); } - (void)test_write_int { size_t i_size = ccz_write_int_size(&a_c); uint8_t bytes[i_size]; ccz_write_int(&a_c, i_size, bytes); XCAssertMemEquals(i_size, bytes, abytes, @"ccz_write_int(a_c)"); ccz_set(r, &a_c); ccz_set_bit(r, 191, 1); size_t j_size = ccz_write_int_size(r); uint8_t jbytes[j_size]; ccz_write_int(r, j_size, jbytes); XCAssertMemEquals(j_size - 1 - CCN_UNIT_SIZE, jbytes + 1 + CCN_UNIT_SIZE, abytes + CCN_UNIT_SIZE, @"ccz_write_int(0x80 a_c)"); XCTAssertEqual(jbytes[0], (uint8_t)0, @"first byte is zero(a_c)"); } - (void)test_read_radix2 { ccz_seti(c, 5047); char input_radix_sign[] = "+1001110110111"; const char *input_radix_nosign=&input_radix_sign[1]; // Positive XCTAssertEqual(ccz_read_radix(r, strlen(input_radix_nosign), input_radix_nosign, 2),(int)0, @"ccz_read_radix return value"); XCTAssertEqual(ccz_cmp(c,r),(int)0, @"ccz_read_radix 1001110110111 base 2 is 5047"); XCTAssertEqual(ccz_read_radix(r, strlen(input_radix_sign), input_radix_sign, 2),(int)0, @"ccz_read_radix return value"); XCTAssertEqual(ccz_cmp(c,r),(int)0, @"ccz_read_radix +1001110110111 base 2 is 5047"); // Negative input_radix_sign[0]='-'; ccz_neg(c); XCTAssertEqual(ccz_read_radix(r, strlen(input_radix_sign), input_radix_sign, 2),(int)0, @"ccz_read_radix return value"); XCTAssertEqual(ccz_cmp(c,r),(int)0, @"ccz_read_radix -1001110110111 base 2 is -5047"); } - (void)test_read_radix16 { ccz_seti(c, 5047); char input_radix_sign[] = "+13B7"; const char *input_radix_nosign=&input_radix_sign[1]; // Positive XCTAssertEqual(ccz_read_radix(r, strlen(input_radix_nosign), input_radix_nosign, 16),(int)0, @"ccz_read_radix return value"); XCTAssertEqual(ccz_cmp(c,r),(int)0, @"ccz_read_radix 13B7 base 16 is 5047"); XCTAssertEqual(ccz_read_radix(r, strlen(input_radix_sign), input_radix_sign, 16),(int)0, @"ccz_read_radix return value"); XCTAssertEqual(ccz_cmp(c,r),(int)0, @"ccz_read_radix +13B7 base 16 is 5047"); // Negative input_radix_sign[0]='-'; ccz_neg(c); XCTAssertEqual(ccz_read_radix(r, strlen(input_radix_sign), input_radix_sign, 16),(int)0, @"ccz_read_radix return value"); XCTAssertEqual(ccz_cmp(c,r),(int)0, @"ccz_read_radix -13B7 base 16 is -5047"); } - (void)test_read_radix10 { ccz_seti(c, 5047); char input_radix_sign[] = "+5047"; const char *input_radix_nosign=&input_radix_sign[1]; // Positive XCTAssertEqual(ccz_read_radix(r, strlen(input_radix_nosign), input_radix_nosign, 10),(int)0, @"ccz_read_radix return value"); XCTAssertEqual(ccz_cmp(c,r),(int)0, @"ccz_read_radix 5047 base 10 is 5047"); XCTAssertEqual(ccz_read_radix(r, strlen(input_radix_sign), input_radix_sign, 10),(int)0, @"ccz_read_radix return value"); XCTAssertEqual(ccz_cmp(c,r),(int)0, @"ccz_read_radix +5047 base 10 is 5047"); // Negative ccz_neg(c); input_radix_sign[0]='-'; XCTAssertEqual(ccz_read_radix(r, strlen(input_radix_sign), input_radix_sign, 10),(int)0, @"ccz_read_radix return value"); XCTAssertEqual(ccz_cmp(c,r),(int)0, @"ccz_read_radix -5047 base 10 is -5047"); } - (void)test_read_radix_error { // Incorrect input const char *input_radix_minus = "-5047A"; const char *input_radix_plus=&input_radix_minus[1]; XCTAssertEqual(ccz_read_radix(r, strlen(input_radix_plus), input_radix_plus, 10),(int)CCZ_INVALID_INPUT_ERROR, @"Detect invalid input - Positive"); ccz_neg(c); XCTAssertEqual(ccz_read_radix(r, strlen(input_radix_minus), input_radix_minus, 10),(int)CCZ_INVALID_INPUT_ERROR, @"Detect invalid input - Negative"); // Incorrect radix XCTAssertEqual(ccz_read_radix(r, strlen(input_radix_plus)-1, input_radix_plus, 65),(int)CCZ_INVALID_RADIX_ERROR, @"Detect invalid radix - Too large"); XCTAssertEqual(ccz_read_radix(r, strlen(input_radix_minus)-1, input_radix_minus, 0),(int)CCZ_INVALID_RADIX_ERROR, @"Detect invalid radix - Too zero"); } - (void)test_write_radix16 { ccz_seti(c, 5047); ccz_neg(c); char buf[1024]; size_t clen_b16 = ccz_write_radix_size(c, 16); XCTAssertEqual(clen_b16, (size_t)5, @"ccz_write_radix_size -5047 base 16 is 5"); buf[0] = (char)0xde; buf[1 + clen_b16] = (char)0xed; ccz_write_radix(c, clen_b16, &buf[1], 16); XCTAssertEqual(buf[0], (char)0xde, @"begin marker ok"); XCTAssertEqual(buf[1 + clen_b16], (char)0xed, @"end marker ok"); XCAssertCharsEquals(clen_b16, &buf[1], "-13B7", @"ccz_write_radix -5047 base 16 is -13B7"); } - (void)test_write_radix10 { ccz_seti(c, 5047); ccz_neg(c); char buf[1024]; size_t clen_b10 = ccz_write_radix_size(c, 10); XCTAssertEqual(clen_b10, (size_t)5, @"ccz_write_radix_size -5047 base 10 is 5"); buf[0] = (char)0xde; buf[1 + clen_b10] = (char)0xed; ccz_write_radix(c, clen_b10, &buf[1], 10); XCTAssertEqual(buf[0], (char)0xde, @"begin marker ok"); XCTAssertEqual(buf[1 + clen_b10], (char)0xed, @"end marker ok"); XCAssertCharsEquals(5, &buf[1], "-5047", @"ccz_write_radix -5047 base 10 is -5047"); } - (void)test_write_radix2 { ccz_seti(c, 5047); ccz_neg(c); char buf[1024]; size_t clen_b2 = ccz_write_radix_size(c, 2); XCTAssertEqual(clen_b2, (size_t)14, @"ccz_write_radix_size -5047 base 2 is 14"); buf[0] = (char)0xde; buf[1 + clen_b2] = (char)0xed; ccz_write_radix(c, clen_b2, &buf[1], 2); XCTAssertEqual(buf[0], (char)0xde, @"begin marker ok"); XCTAssertEqual(buf[1 + clen_b2], (char)0xed, @"end marker ok"); XCAssertCharsEquals(clen_b2, &buf[1], "-1001110110111", @"ccz_write_radix -5047 base 2 is -1001110110111"); } static inline int ccz_readstr(ccz *r, const char *str, unsigned radix) { return ccz_read_radix(r, strlen(str), str, radix); } - (void)test_mod { XCTAssertEqual(ccz_readstr(a, "c968e40c5304364b057425920b18cc358f254ddb0f42f84850d6deec46006b4a692e52b7c3bddead45f77f2c1be1c606521d8a24260429f362d65b57873dbf270e97e210b872e45e97cb4cd87977ad20491e53c48cf0e88da9a61312675a2527c86ac537740c5e4206972f09c0f91fa1c9f14a2cf1be07e82a3b6fd58dc12c3a", 16),(int)0, @"ccz_readstr: ccz_read_radix unexpected failure"); XCTAssertEqual(ccz_readstr(c, "354c912b09ee7abff5b3d94ed52a9e8dcae582e094daa375c495f970710af73efcc4f9776010511f654c7408a6d5d351ab1d94a0fede757d782b54ddcf6fe8d714870b78b0e67a9754cb03a5cf63bbda1c71791902ea4527fb0cd76437391e5422c704ffb6d6018261171d8cee98adcf0243f1fd520fb3761afe94a2f4d99f94", 16),(int)0, @"ccz_readstr: ccz_read_radix unexpected failure"); XCTAssertEqual(ccz_readstr(r, "2983308b3538c60b245899a58b98f08c2e74c53950b30de70314f29af2df858d72df6651a38ceb4f1612231227604c1150c4cc412968c97afa545cbe18ee04a1d102bfa6a5bf7498996a41e70b4c7991f3c9e87984321915b87f8ce5c1aeca2b6015b6384f8a59bae351d662f52f1634c3257434fb8eed85d93fb1ecaf344d7e", 16),(int)0, @"ccz_readstr: ccz_read_radix unexpected failure"); ccz_mod(a, a, c); XCAssertCCZEquals(a, r, @"ccz_mod a = a % c"); // pathological test case from failing SRP ccz_readstr(a, "12573135c66ab09ff6f5dfb777d18756", 16); ccz_readstr(b, "0000000000000010", 16); ccz_readstr(r, "0000000000000006", 16); ccz_mod(c, a, b); XCAssertCCZEquals(c, r, @"ccz_mod a = a % c"); } - (void)test_modmul { ccz_readstr(a, "2983308b3538c60b245899a58b98f08c2e74c53950b30de70314f29af2df858d72df66" "51a38ceb4f1612231227604c1150c4cc412968c97afa545cbe18ee04a1d102bfa6a5bf" "7498996a41e70b4c7991f3c9e87984321915b87f8ce5c1aeca2b6015b6384f8a59bae3" "51d662f52f1634c3257434fb8eed85d93fb1ecaf344d7e", 16); ccz_readstr(b, "fb978a4f4fccdb14c7268918b784c4f6d5281c0d6ff43e60e88e97f97f2617608de248" "8c84eb99a3f467013c860536ec74f4968abeccbc1b026ee5873e40bdd292f8f7416a93" "df619288b49ba21d3e09aa796cb35a340b1abfda4e3b6cd92df2de64967e6a59f78758" "6929c4d2920da20caeb384594d7f2b7e999dab0d6a1ac", 16); ccz_readstr(c, "354c912b09ee7abff5b3d94ed52a9e8dcae582e094daa375c495f970710af73efcc4f9" "776010511f654c7408a6d5d351ab1d94a0fede757d782b54ddcf6fe8d714870b78b0e6" "7a9754cb03a5cf63bbda1c71791902ea4527fb0cd76437391e5422c704ffb6d6018261" "171d8cee98adcf0243f1fd520fb3761afe94a2f4d99f94", 16); ccz_readstr(r, "332f5fc965b485b8c960afbc26e6e278fc134163931602ae89c61246f3131cc62e711e" "637189a3a184eaf28d0ef89572360472f1d0ee625722606d36b031e608704b40840f17" "7ffc6cc392bfe628d51bd8cb5b1a6558ae5c1378f656877490d57d126629318400b866" "756827a525df23f931720250cddab02be65e14b624bfc4", 16); ccz_mulmod(d, a, b, c); XCAssertCCZEquals(d, r, @"ccz_mulmod r = a*b mod c"); ccz_set(d,a); ccz_mulmod(d, d, b, c); XCAssertCCZEquals(d, r, @"ccz_mulmod r = a*b mod c - result in place of a"); ccz_set(d,b); ccz_mulmod(d, a, d, c); XCAssertCCZEquals(d, r, @"ccz_mulmod r = a*b mod c - result in place of b"); } - (void)test_expmod { ccz_seti(a, 2); ccz_seti(b, 64); ccz_seti(c, 0xffffffff); ccz_expmod(d, a, b, c); ccz_seti(a, 1); XCAssertCCZEquals(d, a, @"2**64 mod 0xffffffff = 1?"); ccz_readstr(a, "c968e40c5304364b057425920b18cc358f254ddb0f42f84850d6deec46006b4a692e52b7c3bddead45f77f2c1be1c606521d8a24260429f362d65b57873dbf270e97e210b872e45e97cb4cd87977ad20491e53c48cf0e88da9a61312675a2527c86ac537740c5e4206972f09c0f91fa1c9f14a2cf1be07e82a3b6fd58dc12c3a", 16); ccz_seti(b, 65537); ccz_readstr(c, "354c912b09ee7abff5b3d94ed52a9e8dcae582e094daa375c495f970710af73efcc4f9776010511f654c7408a6d5d351ab1d94a0fede757d782b54ddcf6fe8d714870b78b0e67a9754cb03a5cf63bbda1c71791902ea4527fb0cd76437391e5422c704ffb6d6018261171d8cee98adcf0243f1fd520fb3761afe94a2f4d99f94", 16); ccz_readstr(r, "0fb978a4f4fccdb14c7268918b784c4f6d5281c0d6ff43e60e88e97f97f2617608de2488c84eb99a3f467013c860536ec74f4968abeccbc1b026ee5873e40bdd292f8f7416a93df619288b49ba21d3e09aa796cb35a340b1abfda4e3b6cd92df2de64967e6a59f787586929c4d2920da20caeb384594d7f2b7e999dab0d6a1ac", 16); ccz_expmod(d, a, b, c); XCAssertCCZEquals(d, r, @"ccz_expmod r = (a^b) mod c Test a > c"); ccz_readstr(a, "2983308b3538c60b245899a58b98f08c2e74c53950b30de70314f29af2df858d72df6651a38ceb4f1612231227604c1150c4cc412968c97afa545cbe18ee04a1d102bfa6a5bf7498996a41e70b4c7991f3c9e87984321915b87f8ce5c1aeca2b6015b6384f8a59bae351d662f52f1634c3257434fb8eed85d93fb1ecaf344d7e", 16); ccz_expmod(d, a, b, c); XCAssertCCZEquals(d, r, @"ccz_expmod r = (a^b) mod c Test a normalized < c"); // #if 0 ccz_readstr(r, "8f2fcb71936d463a70f02ef788ef27b363b3bfceb5f0692e8d3bddf74ac35c670f243d05097f99a0e8db9b29b22c6c99cfb8386d92c80c231a756bca77730baa", 16); ccz_readstr(a, "0000000000000002", 16); ccz_readstr(b, "d7ebf1988ad4ce0661ad4e8f52a7d9370fa92de13dac98ea8ccfe929bd4398ff", 16); ccz_readstr(c, "d4c7f8a2b32c11b8fba9581ec4ba4f1b04215642ef7355e37c0fc0443ef756ea2c6b8eeb755a1c723027663caa265ef785b8ff6a9b35227a52d86633dbdfca43", 16); ccz_expmod(d, a, b, c); XCAssertCCZEquals(d, r, @"ccz_expmod r = (a^b) mod c Test small a normalized < c"); // #endif } #if 0 // This works, but currently takes a long time. -(void) test_write_radix10_10kbits { ccz_seti(a, 1); ccz_lsl(b, a, 10000); expected_reallocs += ccz_capacity(b) < ccn_nof(10000); size_t rs = ccz_write_radix_size(b, 10); char bbuf[rs + 1]; bbuf[rs] = 0; ccz_write_radix(b, rs, bbuf, 10); fprintf(stderr, "%s\n", bbuf); } #endif -(void) test_write_radix10_1kbits { ccz_seti(a, 1); ccz_lsl(b, a, 1000); const char expected_result[]="1071508607186267320948425049060001810561404811705533607443750388370351" \ "0511249361224931983788156958581275946729175531468251871452856923140435" \ "9845775746985748039345677748242309854210746050623711418779541821530464" \ "7498358194126739876755916554394607706291457119647768654216766042983165" \ "2624386837205668069376"; expected_reallocs += ccz_capacity(b) < ccn_nof(1000); size_t rs = ccz_write_radix_size(b, 10); char bbuf[rs + 1]; bbuf[rs] = 0; ccz_write_radix(b, rs, bbuf, 10); XCAssertCharsEquals(sizeof(expected_result), bbuf, &expected_result[0], @"ccz_write_radix 2^1000 base 10"); } -(void) test_divmod { ccz_seti(a, 1); ccz_lsl(b, a, 10000); expected_reallocs += (ccz_capacity(a) < ccn_nof(10000)); ccz_seti(c, 64); ccz_mul(d, b, c); ccz_divmod(a, b, d, c); XCTAssertEqual(ccz_is_zero(b), (bool)true, @"remainder is zero"); ccz_lsr(b, a, 10000); ccz_seti(a, 1); XCAssertCCZEquals(b, a, @"((((1 << 10000) * 64) / 64) >> 10000) == 1?"); } - (void)test_set { ccz_set(r, &a_c); XCAssertCCZEquals(r, &a_c, @"ccz_set(r,a_c) r = a_c"); } #if 0 - (void)test_seti { cc_unit r[ccz_nof(_c)]; ccz_seti(r, &a_c[0]); cc_unit s[ccz_nof(_c)] = {}; s[0] = a_c[0]; XCAssertCCZEquals(r, s, @"ccz_seti(r,a_c) r = a_c"); } #endif @end