nx_ecdsa_sig_der_test.nx source
↩ module page · 151 lines · 6803 B
1// nx_ecdsa_sig_der_test.nx -- KAT for the ECDSA DER-sig parser.
2//
3// Test vector: RFC 6979 §A.2.5 (NIST P-256 + SHA-256, "sample")
4// r = EFD48B2AACB6A8FD1140DD9CD45E81D6 9D2C877B56AAF991C34D0EA84EAF3716
5// s = F7CB1C942D657C41D436C7A1B6E29F65 F3E900DBB9AFF4064DC4AB2F843ACDA8
6//
7// Both r and s have their leading byte's high bit set (0xEF and
8// 0xF7 respectively), so DER encoding prepends 0x00 to each ->
9// 33-byte INTEGER bodies.
10//
11// expect_exit: 0
12// license_tier: ORIGINAL
13
14import "nx_syscalls.nx"
15import "nx_u256.nx"
16import "nx_ecdsa_sig_der.nx"
17
18func main() -> i64 {
19 // ---- Build RFC 6979 §A.2.5 DER-encoded sig ----
20 // 30 46 SEQUENCE length 70
21 // 02 21 00 EF D4 ... 37 16 INTEGER (33 bytes) r
22 // 02 21 00 F7 CB ... CD A8 INTEGER (33 bytes) s
23 // total: 2 + 35 + 35 = 72 bytes
24 let buf: *u8 = sys_mmap(128)
25 buf[0] = 0x30; buf[1] = 0x46 // SEQUENCE 70
26
27 // INTEGER tag + length + 0x00 + 32-byte r
28 buf[2] = 0x02; buf[3] = 0x21; buf[4] = 0x00
29 buf[5] = 0xEF; buf[6] = 0xD4; buf[7] = 0x8B; buf[8] = 0x2A
30 buf[9] = 0xAC; buf[10] = 0xB6; buf[11] = 0xA8; buf[12] = 0xFD
31 buf[13] = 0x11; buf[14] = 0x40; buf[15] = 0xDD; buf[16] = 0x9C
32 buf[17] = 0xD4; buf[18] = 0x5E; buf[19] = 0x81; buf[20] = 0xD6
33 buf[21] = 0x9D; buf[22] = 0x2C; buf[23] = 0x87; buf[24] = 0x7B
34 buf[25] = 0x56; buf[26] = 0xAA; buf[27] = 0xF9; buf[28] = 0x91
35 buf[29] = 0xC3; buf[30] = 0x4D; buf[31] = 0x0E; buf[32] = 0xA8
36 buf[33] = 0x4E; buf[34] = 0xAF; buf[35] = 0x37; buf[36] = 0x16
37
38 // INTEGER tag + length + 0x00 + 32-byte s
39 buf[37] = 0x02; buf[38] = 0x21; buf[39] = 0x00
40 buf[40] = 0xF7; buf[41] = 0xCB; buf[42] = 0x1C; buf[43] = 0x94
41 buf[44] = 0x2D; buf[45] = 0x65; buf[46] = 0x7C; buf[47] = 0x41
42 buf[48] = 0xD4; buf[49] = 0x36; buf[50] = 0xC7; buf[51] = 0xA1
43 buf[52] = 0xB6; buf[53] = 0xE2; buf[54] = 0x9F; buf[55] = 0x65
44 buf[56] = 0xF3; buf[57] = 0xE9; buf[58] = 0x00; buf[59] = 0xDB
45 buf[60] = 0xB9; buf[61] = 0xAF; buf[62] = 0xF4; buf[63] = 0x06
46 buf[64] = 0x4D; buf[65] = 0xC4; buf[66] = 0xAB; buf[67] = 0x2F
47 buf[68] = 0x84; buf[69] = 0x3A; buf[70] = 0xCD; buf[71] = 0xA8
48
49 let der_total: i64 = 72
50 let r: *i64 = u256_alloc()
51 let s: *i64 = u256_alloc()
52
53 // ---- Test A: parse succeeds + extracts known values ----
54 let v: i64 = nx_ecdsa_sig_parse_der(buf, der_total, r, s)
55 if v != NX_ECDSA_DER_OK { return 1 }
56
57 // Verify r limbs (LE) against the expected BE bytes:
58 // limb[7] = 0xEFD48B2A (top of r)
59 // limb[0] = 0x4EAF3716 (bottom of r)
60 if r[7] != 0xEFD48B2A { return 2 }
61 if r[6] != 0xACB6A8FD { return 3 }
62 if r[5] != 0x1140DD9C { return 4 }
63 if r[4] != 0xD45E81D6 { return 5 }
64 if r[3] != 0x9D2C877B { return 6 }
65 if r[2] != 0x56AAF991 { return 7 }
66 if r[1] != 0xC34D0EA8 { return 8 }
67 if r[0] != 0x4EAF3716 { return 9 }
68
69 // Verify s limbs:
70 if s[7] != 0xF7CB1C94 { return 10 }
71 if s[6] != 0x2D657C41 { return 11 }
72 if s[5] != 0xD436C7A1 { return 12 }
73 if s[4] != 0xB6E29F65 { return 13 }
74 if s[3] != 0xF3E900DB { return 14 }
75 if s[2] != 0xB9AFF406 { return 15 }
76 if s[1] != 0x4DC4AB2F { return 16 }
77 if s[0] != 0x843ACDA8 { return 17 }
78
79 // ---- Test B: short INTEGER (< 32 bytes -> zero-pad high) ----
80 // 30 06 02 01 05 02 01 07 (r=5, s=7)
81 let small: *u8 = sys_mmap(32)
82 small[0]=0x30; small[1]=0x06; small[2]=0x02; small[3]=0x01
83 small[4]=0x05; small[5]=0x02; small[6]=0x01; small[7]=0x07
84 let r2: *i64 = u256_alloc()
85 let s2: *i64 = u256_alloc()
86 if nx_ecdsa_sig_parse_der(small, 8, r2, s2) != NX_ECDSA_DER_OK { return 20 }
87 if r2[0] != 5 { return 21 }
88 if s2[0] != 7 { return 22 }
89 var i: i64 = 1
90 while i < 8 {
91 if r2[i] != 0 { return 23 }
92 if s2[i] != 0 { return 24 }
93 i = i + 1
94 }
95
96 // ---- Test C: outer tag != SEQUENCE ----
97 let bad_outer: *u8 = sys_mmap(16)
98 bad_outer[0]=0x99; bad_outer[1]=0x00
99 if nx_ecdsa_sig_parse_der(bad_outer, 2, r2, s2) != NX_ECDSA_DER_BAD_OUTER { return 30 }
100
101 // ---- Test D: r tag != INTEGER ----
102 let bad_r: *u8 = sys_mmap(16)
103 bad_r[0]=0x30; bad_r[1]=0x02; bad_r[2]=0x99; bad_r[3]=0x00
104 if nx_ecdsa_sig_parse_der(bad_r, 4, r2, s2) != NX_ECDSA_DER_BAD_R { return 40 }
105
106 // ---- Test E: s tag != INTEGER ----
107 let bad_s: *u8 = sys_mmap(16)
108 bad_s[0]=0x30; bad_s[1]=0x05; bad_s[2]=0x02; bad_s[3]=0x01
109 bad_s[4]=0x05; bad_s[5]=0x99; bad_s[6]=0x00
110 if nx_ecdsa_sig_parse_der(bad_s, 7, r2, s2) != NX_ECDSA_DER_BAD_S { return 50 }
111
112 // ---- Test F: oversized INTEGER (34 bytes) rejected ----
113 let big_int: *u8 = sys_mmap(64)
114 big_int[0]=0x30; big_int[1]=0x24 // SEQUENCE 36
115 big_int[2]=0x02; big_int[3]=0x22 // INTEGER 34 bytes
116 var bi: i64 = 0
117 while bi < 34 { big_int[4 + bi] = 0xAA as u8; bi = bi + 1 }
118 if nx_ecdsa_sig_parse_der(big_int, 38, r2, s2) != NX_ECDSA_DER_LEN_TOO_BIG { return 60 }
119
120 // ---- Test G: 33-byte INTEGER without leading 0x00 rejected ----
121 let bad_pad: *u8 = sys_mmap(64)
122 bad_pad[0]=0x30; bad_pad[1]=0x23 // SEQUENCE 35
123 bad_pad[2]=0x02; bad_pad[3]=0x21 // INTEGER 33 bytes
124 bad_pad[4]=0x77 // NOT 0x00
125 bi = 0
126 while bi < 32 { bad_pad[5 + bi] = 0xBB as u8; bi = bi + 1 }
127 if nx_ecdsa_sig_parse_der(bad_pad, 37, r2, s2) != NX_ECDSA_DER_LEN_TOO_BIG { return 70 }
128
129 // ---- Test H: trailing bytes inside outer SEQUENCE rejected ----
130 // 30 09 02 01 05 02 01 07 02 01 09 (3 INTEGERs instead of 2)
131 let trail: *u8 = sys_mmap(16)
132 trail[0]=0x30; trail[1]=0x09
133 trail[2]=0x02; trail[3]=0x01; trail[4]=0x05
134 trail[5]=0x02; trail[6]=0x01; trail[7]=0x07
135 trail[8]=0x02; trail[9]=0x01; trail[10]=0x09
136 if nx_ecdsa_sig_parse_der(trail, 11, r2, s2) != NX_ECDSA_DER_TRAILING { return 80 }
137
138 // ---- Test I: verdict gate ----
139 if nx_ecdsa_sig_der_verdict_is_valid(NX_ECDSA_DER_OK) != 1 { return 90 }
140 if nx_ecdsa_sig_der_verdict_is_valid(NX_ECDSA_DER_BAD_OUTER) != 1 { return 91 }
141 if nx_ecdsa_sig_der_verdict_is_valid(NX_ECDSA_DER_BAD_R) != 1 { return 92 }
142 if nx_ecdsa_sig_der_verdict_is_valid(NX_ECDSA_DER_BAD_S) != 1 { return 93 }
143 if nx_ecdsa_sig_der_verdict_is_valid(NX_ECDSA_DER_LEN_TOO_BIG) != 1 { return 94 }
144 if nx_ecdsa_sig_der_verdict_is_valid(NX_ECDSA_DER_TRAILING) != 1 { return 95 }
145 if nx_ecdsa_sig_der_verdict_is_valid(NX_ECDSA_DER_VERDICT_N) != 0 { return 96 }
146 if nx_ecdsa_sig_der_verdict_is_valid(0) != 0 { return 97 }
147 if nx_ecdsa_sig_der_verdict_is_valid(0 - 1) != 0 { return 98 }
148 if nx_ecdsa_sig_der_verdict_is_valid(999) != 0 { return 99 }
149
150 return 0
151}