code wiki / (root) / nx_p256_modn_test.nx

nx_p256_modn_test.nx source

↩ module page · 138 lines · 4482 B

1// nx_p256_modn_test.nx -- KAT for arithmetic in Z/nZ where n is 2// the NIST P-256 group order. 3// 4// expect_exit: 0 5// license_tier: ORIGINAL 6 7import "nx_syscalls.nx" 8import "nx_u256.nx" 9import "nx_p256_modn.nx" 10 11func main() -> i64 { 12 let a: *i64 = u256_alloc() 13 let b: *i64 = u256_alloc() 14 let r: *i64 = u256_alloc() 15 let tmp: *i64 = u256_alloc() 16 let n: *i64 = u256_alloc() 17 p256_modn_load_n(n) 18 let one: *i64 = u256_alloc() 19 p256_modn_one(one) 20 21 // ---- Test A: load_n byte-exact (BE bytes against FIPS 186-5) ---- 22 let n_bytes: *u8 = sys_mmap(32) 23 u256_store_be(n_bytes, n) 24 // Expected BE: FF FF FF FF 00 00 00 00 FF FF FF FF FF FF FF FF 25 // BC E6 FA AD A7 17 9E 84 F3 B9 CA C2 FC 63 25 51 26 if (n_bytes[0] & 0xff) != 0xFF { return 1 } 27 if (n_bytes[3] & 0xff) != 0xFF { return 2 } 28 if (n_bytes[4] & 0xff) != 0x00 { return 3 } 29 if (n_bytes[7] & 0xff) != 0x00 { return 4 } 30 if (n_bytes[15] & 0xff) != 0xFF { return 5 } 31 if (n_bytes[16] & 0xff) != 0xBC { return 6 } 32 if (n_bytes[28] & 0xff) != 0xFC { return 7 } 33 if (n_bytes[31] & 0xff) != 0x51 { return 8 } 34 35 // ---- Test B: load_n_minus_2 differs only in LSB limb ---- 36 let nm2: *i64 = u256_alloc() 37 p256_modn_load_n_minus_2(nm2) 38 if nm2[0] != 0xFC63254F { return 11 } 39 var i: i64 = 1 40 while i < 8 { 41 if (nm2[i] & 0xFFFFFFFF) != (n[i] & 0xFFFFFFFF) { return 12 + i } 42 i = i + 1 43 } 44 45 // ---- Test C: add 1 + 1 = 2 ---- 46 p256_modn_one(a) 47 p256_modn_one(b) 48 p256_modn_add(r, a, b) 49 if r[0] != 2 { return 20 } 50 51 // ---- Test D: (n-1) + 1 = 0 (boundary wrap) ---- 52 let nm1: *i64 = u256_alloc() 53 u256_copy(nm1, n) 54 p256_modn_sub(nm1, nm1, one) 55 p256_modn_add(r, nm1, one) 56 if u256_is_zero(r) != 1 { return 30 } 57 58 // ---- Test E: 0 - 1 = n-1 (underflow + add-n) ---- 59 p256_modn_zero(a) 60 p256_modn_sub(r, a, one) 61 if p256_modn_eq(r, nm1) != 1 { return 40 } 62 63 // ---- Test F: -1 = n-1 ---- 64 p256_modn_neg(r, one) 65 if p256_modn_eq(r, nm1) != 1 { return 50 } 66 67 // ---- Test G: a*1 = a ---- 68 u256_zero(a) 69 a[0] = 0x12345678; a[3] = 0xABCDEF01; a[5] = 0x55555555 70 if u256_cmp(a, n) != (0 - 1) { return 60 } // canonical check 71 p256_modn_mul(r, a, one) 72 if p256_modn_eq(r, a) != 1 { return 61 } 73 74 // ---- Test H: 2 * 3 = 6 ---- 75 u256_zero(a); a[0] = 2 76 u256_zero(b); b[0] = 3 77 p256_modn_mul(r, a, b) 78 if r[0] != 6 { return 70 } 79 i = 1 80 while i < 8 { 81 if r[i] != 0 { return 71 } 82 i = i + 1 83 } 84 85 // ---- Test I: (n-1) * (n-1) = 1 (since -1 * -1 = 1 mod n) ---- 86 p256_modn_mul(r, nm1, nm1) 87 if p256_modn_eq(r, one) != 1 { return 80 } 88 89 // ---- Test J: commutativity a*b == b*a ---- 90 u256_zero(a); a[0] = 0x11111111; a[3] = 0x22222222 91 u256_zero(b); b[1] = 0xABCDEF01; b[7] = 0x00FFFFFF 92 if u256_cmp(a, n) != (0 - 1) { return 90 } 93 if u256_cmp(b, n) != (0 - 1) { return 91 } 94 let r2: *i64 = u256_alloc() 95 p256_modn_mul(r, a, b) 96 p256_modn_mul(r2, b, a) 97 if p256_modn_eq(r, r2) != 1 { return 92 } 98 99 // ---- Test K: inv(1) = 1 ---- 100 p256_modn_inv(r, one) 101 if p256_modn_eq(r, one) != 1 { return 100 } 102 103 // ---- Test L: inv(2) * 2 = 1 ---- 104 u256_zero(a); a[0] = 2 105 p256_modn_inv(r, a) 106 p256_modn_mul(r2, r, a) 107 if p256_modn_eq(r2, one) != 1 { return 110 } 108 109 // ---- Test M: random a * inv(a) = 1 ---- 110 u256_zero(a) 111 a[0] = 0xDEADBEEF; a[2] = 0xCAFEBABE; a[5] = 0x77777777 112 if u256_cmp(a, n) != (0 - 1) { return 120 } 113 p256_modn_inv(r, a) 114 p256_modn_mul(r2, r, a) 115 if p256_modn_eq(r2, one) != 1 { return 121 } 116 117 // ---- Test N: reduce(a) where a < n -> a unchanged ---- 118 u256_zero(a); a[0] = 0x12345678 119 p256_modn_reduce(r, a) 120 if p256_modn_eq(r, a) != 1 { return 130 } 121 122 // ---- Test O: reduce(a) where a == 2^256 - 1 (> n) ---- 123 i = 0 124 while i < 8 { a[i] = 0xFFFFFFFF; i = i + 1 } 125 // a = 2^256 - 1; n = 2^256 - 2^224 + 2^192 + (some bits); a > n. 126 // Expected: a - n 127 p256_modn_reduce(r, a) 128 // Verify r = (2^256 - 1) - n via re-add: r + n should equal a (with overflow). 129 let check: *i64 = u256_alloc() 130 let carry: i64 = u256_add_with_carry(check, r, n) 131 // Since (2^256 - 1) + n - n = 2^256 - 1, we expect carry == 0 and check == a. 132 if carry != 0 { return 140 } 133 if u256_eq(check, a) != 1 { return 141 } 134 // Also: r < n 135 if u256_cmp(r, n) != (0 - 1) { return 142 } 136 137 return 0 138}