nx_nss_certdata_parse_test.nx source
↩ module page · 156 lines · 7894 B
1// nx_nss_certdata_parse_test.nx -- KAT for the Mozilla NSS
2// certdata.txt parser.
3//
4// expect_exit: 0
5// license_tier: ORIGINAL
6
7import "nx_syscalls.nx"
8import "nx_nss_certdata_parse.nx"
9
10// Helper: write a string literal into buf at off. Returns bytes
11// written (= string length).
12func wstr(buf: *u8, off: i64, src: *u8, n: i64) -> i64 {
13 var i: i64 = 0
14 while i < n {
15 buf[off + i] = src[i]
16 i = i + 1
17 }
18 return n
19}
20
21// Quick string-helper: build "string" bytes inline since nx
22// string literals can't easily be cast to *u8 mid-expression.
23
24func main() -> i64 {
25 // ---- Test A: synthetic 1-cert certdata input ----
26 // Build:
27 // #
28 // # Test cert
29 // #
30 // CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE
31 // CKA_LABEL UTF8 "Test"
32 // CKA_VALUE MULTILINE_OCTAL
33 // \101\102\103\104\105
34 // END
35 //
36 // Expected DER output: bytes 0x41 0x42 0x43 0x44 0x45 = "ABCDE".
37 let in_buf: *u8 = sys_mmap(256)
38 var p: i64 = 0
39 // "#\n"
40 in_buf[p]=0x23; in_buf[p+1]=0x0A; p = p + 2
41 // "# Test cert\n"
42 in_buf[p]=0x23; in_buf[p+1]=0x20; in_buf[p+2]=0x54; in_buf[p+3]=0x65
43 in_buf[p+4]=0x73; in_buf[p+5]=0x74; in_buf[p+6]=0x20; in_buf[p+7]=0x63
44 in_buf[p+8]=0x65; in_buf[p+9]=0x72; in_buf[p+10]=0x74; in_buf[p+11]=0x0A
45 p = p + 12
46 // "#\n"
47 in_buf[p]=0x23; in_buf[p+1]=0x0A; p = p + 2
48 // "CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE\n" -- 42 bytes
49 in_buf[p]=0x43; in_buf[p+1]=0x4B; in_buf[p+2]=0x41; in_buf[p+3]=0x5F // CKA_
50 in_buf[p+4]=0x43; in_buf[p+5]=0x4C; in_buf[p+6]=0x41; in_buf[p+7]=0x53 // CLAS
51 in_buf[p+8]=0x53; in_buf[p+9]=0x20 // S<sp>
52 in_buf[p+10]=0x43; in_buf[p+11]=0x4B; in_buf[p+12]=0x5F // CK_
53 in_buf[p+13]=0x4F; in_buf[p+14]=0x42; in_buf[p+15]=0x4A; in_buf[p+16]=0x45 // OBJE
54 in_buf[p+17]=0x43; in_buf[p+18]=0x54; in_buf[p+19]=0x5F // CT_
55 in_buf[p+20]=0x43; in_buf[p+21]=0x4C; in_buf[p+22]=0x41; in_buf[p+23]=0x53 // CLAS
56 in_buf[p+24]=0x53; in_buf[p+25]=0x20 // S<sp>
57 in_buf[p+26]=0x43; in_buf[p+27]=0x4B; in_buf[p+28]=0x4F; in_buf[p+29]=0x5F // CKO_
58 in_buf[p+30]=0x43; in_buf[p+31]=0x45; in_buf[p+32]=0x52; in_buf[p+33]=0x54 // CERT
59 in_buf[p+34]=0x49; in_buf[p+35]=0x46; in_buf[p+36]=0x49; in_buf[p+37]=0x43 // IFIC
60 in_buf[p+38]=0x41; in_buf[p+39]=0x54; in_buf[p+40]=0x45 // ATE
61 in_buf[p+41]=0x0A
62 p = p + 42
63 // "CKA_LABEL UTF8 \"Test\"\n" -- 22 bytes
64 in_buf[p]=0x43; in_buf[p+1]=0x4B; in_buf[p+2]=0x41; in_buf[p+3]=0x5F // CKA_
65 in_buf[p+4]=0x4C; in_buf[p+5]=0x41; in_buf[p+6]=0x42; in_buf[p+7]=0x45 // LABE
66 in_buf[p+8]=0x4C; in_buf[p+9]=0x20 // L<sp>
67 in_buf[p+10]=0x55; in_buf[p+11]=0x54; in_buf[p+12]=0x46; in_buf[p+13]=0x38 // UTF8
68 in_buf[p+14]=0x20; in_buf[p+15]=0x22 // <sp>"
69 in_buf[p+16]=0x54; in_buf[p+17]=0x65; in_buf[p+18]=0x73; in_buf[p+19]=0x74 // Test
70 in_buf[p+20]=0x22; in_buf[p+21]=0x0A // "\n
71 p = p + 22
72 // "CKA_VALUE MULTILINE_OCTAL\n" -- 26 bytes
73 in_buf[p]=0x43; in_buf[p+1]=0x4B; in_buf[p+2]=0x41; in_buf[p+3]=0x5F // CKA_
74 in_buf[p+4]=0x56; in_buf[p+5]=0x41; in_buf[p+6]=0x4C; in_buf[p+7]=0x55 // VALU
75 in_buf[p+8]=0x45; in_buf[p+9]=0x20 // E<sp>
76 in_buf[p+10]=0x4D; in_buf[p+11]=0x55; in_buf[p+12]=0x4C; in_buf[p+13]=0x54 // MULT
77 in_buf[p+14]=0x49; in_buf[p+15]=0x4C; in_buf[p+16]=0x49; in_buf[p+17]=0x4E // ILIN
78 in_buf[p+18]=0x45; in_buf[p+19]=0x5F // E_
79 in_buf[p+20]=0x4F; in_buf[p+21]=0x43; in_buf[p+22]=0x54; in_buf[p+23]=0x41 // OCTA
80 in_buf[p+24]=0x4C; in_buf[p+25]=0x0A // L\n
81 p = p + 26
82 // "\\101\\102\\103\\104\\105\n" -- 21 bytes (5 escapes of 4 + \n)
83 in_buf[p]=0x5C; in_buf[p+1]=0x31; in_buf[p+2]=0x30; in_buf[p+3]=0x31 // \101
84 in_buf[p+4]=0x5C; in_buf[p+5]=0x31; in_buf[p+6]=0x30; in_buf[p+7]=0x32 // \102
85 in_buf[p+8]=0x5C; in_buf[p+9]=0x31; in_buf[p+10]=0x30; in_buf[p+11]=0x33 // \103
86 in_buf[p+12]=0x5C; in_buf[p+13]=0x31; in_buf[p+14]=0x30; in_buf[p+15]=0x34 // \104
87 in_buf[p+16]=0x5C; in_buf[p+17]=0x31; in_buf[p+18]=0x30; in_buf[p+19]=0x35 // \105
88 in_buf[p+20]=0x0A
89 p = p + 21
90 // "END\n"
91 in_buf[p]=0x45; in_buf[p+1]=0x4E; in_buf[p+2]=0x44; in_buf[p+3]=0x0A
92 p = p + 4
93
94 let in_len_total: i64 = p // 131
95 if in_len_total != 131 { return 1 }
96
97 let out_buf: *u8 = sys_mmap(256)
98 let n_p: *i64 = sys_mmap(16) as *i64
99 let v: i64 = nx_nss_certdata_parse(in_buf, in_len_total, out_buf, 256, n_p)
100 if v != NX_NSS_CD_OK { return 2 }
101 if *n_p != 1 { return 3 }
102 // out_buf header: 2-byte cert_count BE
103 if out_buf[0] != 0x00 { return 4 }
104 if out_buf[1] != 0x01 { return 5 }
105 // Cert entry: 3-byte len BE + 5 DER bytes
106 if out_buf[2] != 0x00 { return 6 }
107 if out_buf[3] != 0x00 { return 7 }
108 if out_buf[4] != 0x05 { return 8 }
109 if out_buf[5] != 0x41 { return 9 } // 'A' = 0x41 = octal 101
110 if out_buf[6] != 0x42 { return 10 } // 'B' = 0x42 = octal 102
111 if out_buf[7] != 0x43 { return 11 } // 'C' = 0x43 = octal 103
112 if out_buf[8] != 0x44 { return 12 } // 'D' = 0x44 = octal 104
113 if out_buf[9] != 0x45 { return 13 } // 'E' = 0x45 = octal 105
114
115 // ---- Test B: empty input -> NO_CERTS ----
116 let empty_in: *u8 = sys_mmap(8)
117 if nx_nss_certdata_parse(empty_in, 0, out_buf, 256, n_p) != NX_NSS_CD_NO_CERTS { return 20 }
118
119 // ---- Test C: input with no CKO_CERTIFICATE marker -> NO_CERTS ----
120 // Just a comment line
121 let no_certs: *u8 = sys_mmap(16)
122 no_certs[0]=0x23; no_certs[1]=0x20; no_certs[2]=0x68; no_certs[3]=0x69; no_certs[4]=0x0A // "# hi\n"
123 if nx_nss_certdata_parse(no_certs, 5, out_buf, 256, n_p) != NX_NSS_CD_NO_CERTS { return 21 }
124
125 // ---- Test D: output buffer too small -> OUTPUT_FULL ----
126 // Re-run the Test A input but with out_cap = 5 (smaller than the
127 // 2-byte header + 3-byte cert_len + 5 DER = 10 needed).
128 let small_out: *u8 = sys_mmap(16)
129 if nx_nss_certdata_parse(in_buf, in_len_total, small_out, 5, n_p) != NX_NSS_CD_OUTPUT_FULL { return 22 }
130
131 // ---- Test E: bad octal escape (\189 has digit '9' which is non-octal) -> BAD_ESCAPE ----
132 // Replace the first escape in Test A's value block with \189.
133 let bad_in: *u8 = sys_mmap(256)
134 var bi: i64 = 0
135 while bi < in_len_total { bad_in[bi] = in_buf[bi]; bi = bi + 1 }
136 // Octal line starts at offset 2+12+2+42+22+26 = 106
137 // First escape is at 106..110: \101 -> replace bytes 107,108,109 with "189"
138 bad_in[107] = 0x31 // '1'
139 bad_in[108] = 0x38 // '8'
140 bad_in[109] = 0x39 // '9' (non-octal)
141 if nx_nss_certdata_parse(bad_in, in_len_total, out_buf, 256, n_p) != NX_NSS_CD_BAD_ESCAPE { return 23 }
142
143 // ---- Test F: verdict gate ----
144 if nx_nss_certdata_verdict_is_valid(NX_NSS_CD_OK) != 1 { return 30 }
145 if nx_nss_certdata_verdict_is_valid(NX_NSS_CD_TRUNCATED) != 1 { return 31 }
146 if nx_nss_certdata_verdict_is_valid(NX_NSS_CD_BAD_ESCAPE) != 1 { return 32 }
147 if nx_nss_certdata_verdict_is_valid(NX_NSS_CD_OUTPUT_FULL) != 1 { return 33 }
148 if nx_nss_certdata_verdict_is_valid(NX_NSS_CD_NO_CERTS) != 1 { return 34 }
149 if nx_nss_certdata_verdict_is_valid(NX_NSS_CD_TOO_MANY) != 1 { return 35 }
150 if nx_nss_certdata_verdict_is_valid(NX_NSS_CD_BAD_DER_SIZE) != 1 { return 36 }
151 if nx_nss_certdata_verdict_is_valid(NX_NSS_CD_VERDICT_N) != 0 { return 37 }
152 if nx_nss_certdata_verdict_is_valid(0) != 0 { return 38 }
153 if nx_nss_certdata_verdict_is_valid(0 - 1) != 0 { return 39 }
154
155 return 0
156}