code wiki / (root) / nx_x509_pubkey_ec_test.nx

nx_x509_pubkey_ec_test.nx source

↩ module page · 123 lines · 5736 B

1// nx_x509_pubkey_ec_test.nx -- KAT for ECDSA-P256 pubkey extraction 2// from a parsed X509Cert. 3// 4// Uses the RFC 6979 §A.2.5 pubkey (a known-on-curve P-256 point) 5// laid out in uncompressed format (0x04 || X || Y) inside a 6// synthetic buffer at a known offset. Tests: 7// - happy path: extract X, Y match the documented limbs 8// - bad length (e.g. 64 or 66 bytes) -> BAD_LEN 9// - wrong leading byte (0x02 instead of 0x04) -> NOT_UNCOMPRESSED 10// - verdict gate 11// 12// expect_exit: 0 13// license_tier: ORIGINAL 14 15import "nx_syscalls.nx" 16import "nx_u256.nx" 17import "nx_x509.nx" 18import "nx_x509_pubkey_ec.nx" 19 20func main() -> i64 { 21 // ---- Build a 65-byte uncompressed P-256 pubkey (RFC 6979 §A.2.5) ---- 22 let pk: *u8 = sys_mmap(128) 23 pk[0] = 0x04 // uncompressed indicator 24 // X coordinate (32 bytes BE) 25 pk[1] = 0x60; pk[2] = 0xFE; pk[3] = 0xD4; pk[4] = 0xBA 26 pk[5] = 0x25; pk[6] = 0x5A; pk[7] = 0x9D; pk[8] = 0x31 27 pk[9] = 0xC9; pk[10] = 0x61; pk[11] = 0xEB; pk[12] = 0x74 28 pk[13] = 0xC6; pk[14] = 0x35; pk[15] = 0x6D; pk[16] = 0x68 29 pk[17] = 0xC0; pk[18] = 0x49; pk[19] = 0xB8; pk[20] = 0x92 30 pk[21] = 0x3B; pk[22] = 0x61; pk[23] = 0xFA; pk[24] = 0x6C 31 pk[25] = 0xE6; pk[26] = 0x69; pk[27] = 0x62; pk[28] = 0x2E 32 pk[29] = 0x60; pk[30] = 0xF2; pk[31] = 0x9F; pk[32] = 0xB6 33 // Y coordinate (32 bytes BE) 34 pk[33] = 0x79; pk[34] = 0x03; pk[35] = 0xFE; pk[36] = 0x10 35 pk[37] = 0x08; pk[38] = 0xB8; pk[39] = 0xBC; pk[40] = 0x99 36 pk[41] = 0xA4; pk[42] = 0x1A; pk[43] = 0xE9; pk[44] = 0xE9 37 pk[45] = 0x56; pk[46] = 0x28; pk[47] = 0xBC; pk[48] = 0x64 38 pk[49] = 0xF2; pk[50] = 0xF1; pk[51] = 0xB2; pk[52] = 0x0C 39 pk[53] = 0x2D; pk[54] = 0x7E; pk[55] = 0x9F; pk[56] = 0x51 40 pk[57] = 0x77; pk[58] = 0xA3; pk[59] = 0xC2; pk[60] = 0x94 41 pk[61] = 0xD4; pk[62] = 0x46; pk[63] = 0x22; pk[64] = 0x99 42 43 // ---- Build a manual X509Cert with pubkey_off/_len pointed at it ---- 44 let cert_raw: *u8 = sys_mmap(256) 45 let cert: *X509Cert = cert_raw as *X509Cert 46 cert.tbs_off = 0; cert.tbs_len = 0 47 cert.serial_off = 0; cert.serial_len = 0 48 cert.sig_alg_off = 0; cert.sig_alg_len = 0 49 cert.spki_off = 0; cert.spki_len = 0 50 cert.sig_off = 0; cert.sig_len = 0 51 cert.pubkey_off = 0; cert.pubkey_len = 65 // <-- points at pk[0..65] 52 cert.pubkey_alg_off = 0; cert.pubkey_alg_len = 0 53 cert.validity_off = 0; cert.validity_len = 0 54 cert.extensions_off = 0 - 1; cert.extensions_len = 0 55 56 // ---- Test A: extract OK ---- 57 let x: *i64 = u256_alloc() 58 let y: *i64 = u256_alloc() 59 let v: i64 = nx_x509_pubkey_extract_ec_p256(pk, cert, x, y) 60 if v != NX_X509_PUBKEY_EC_OK { return 1 } 61 62 // Verify X limbs (LE; limb[7] = top of X = 0x60FED4BA, limb[0] = LSB = 0x60F29FB6) 63 if x[7] != 0x60FED4BA { return 2 } 64 if x[6] != 0x255A9D31 { return 3 } 65 if x[5] != 0xC961EB74 { return 4 } 66 if x[4] != 0xC6356D68 { return 5 } 67 if x[3] != 0xC049B892 { return 6 } 68 if x[2] != 0x3B61FA6C { return 7 } 69 if x[1] != 0xE669622E { return 8 } 70 if x[0] != 0x60F29FB6 { return 9 } 71 72 // Verify Y limbs 73 if y[7] != 0x7903FE10 { return 10 } 74 if y[6] != 0x08B8BC99 { return 11 } 75 if y[5] != 0xA41AE9E9 { return 12 } 76 if y[4] != 0x5628BC64 { return 13 } 77 if y[3] != 0xF2F1B20C { return 14 } 78 if y[2] != 0x2D7E9F51 { return 15 } 79 if y[1] != 0x77A3C294 { return 16 } 80 if y[0] != 0xD4462299 { return 17 } 81 82 // ---- Test B: wrong length -> BAD_LEN ---- 83 cert.pubkey_len = 64 84 if nx_x509_pubkey_extract_ec_p256(pk, cert, x, y) != NX_X509_PUBKEY_EC_BAD_LEN { return 20 } 85 cert.pubkey_len = 66 86 if nx_x509_pubkey_extract_ec_p256(pk, cert, x, y) != NX_X509_PUBKEY_EC_BAD_LEN { return 21 } 87 cert.pubkey_len = 0 88 if nx_x509_pubkey_extract_ec_p256(pk, cert, x, y) != NX_X509_PUBKEY_EC_BAD_LEN { return 22 } 89 cert.pubkey_len = 65 90 91 // ---- Test C: wrong leading byte -> NOT_UNCOMPRESSED ---- 92 pk[0] = 0x02 // compressed indicator 93 if nx_x509_pubkey_extract_ec_p256(pk, cert, x, y) != NX_X509_PUBKEY_EC_NOT_UNCOMPRESSED { return 30 } 94 pk[0] = 0x03 95 if nx_x509_pubkey_extract_ec_p256(pk, cert, x, y) != NX_X509_PUBKEY_EC_NOT_UNCOMPRESSED { return 31 } 96 pk[0] = 0x05 // hybrid (deprecated) 97 if nx_x509_pubkey_extract_ec_p256(pk, cert, x, y) != NX_X509_PUBKEY_EC_NOT_UNCOMPRESSED { return 32 } 98 pk[0] = 0x00 99 if nx_x509_pubkey_extract_ec_p256(pk, cert, x, y) != NX_X509_PUBKEY_EC_NOT_UNCOMPRESSED { return 33 } 100 pk[0] = 0x04 // restore 101 102 // ---- Test D: extract at nonzero pubkey_off (cert-realistic) ---- 103 let bigger: *u8 = sys_mmap(128) 104 var i: i64 = 0 105 while i < 128 { bigger[i] = 0xCC; i = i + 1 } 106 i = 0 107 while i < 65 { bigger[10 + i] = pk[i]; i = i + 1 } 108 cert.pubkey_off = 10 109 if nx_x509_pubkey_extract_ec_p256(bigger, cert, x, y) != NX_X509_PUBKEY_EC_OK { return 40 } 110 if x[7] != 0x60FED4BA { return 41 } 111 if y[0] != 0xD4462299 { return 42 } 112 113 // ---- Test E: verdict gate ---- 114 if nx_x509_pubkey_ec_verdict_is_valid(NX_X509_PUBKEY_EC_OK) != 1 { return 50 } 115 if nx_x509_pubkey_ec_verdict_is_valid(NX_X509_PUBKEY_EC_BAD_LEN) != 1 { return 51 } 116 if nx_x509_pubkey_ec_verdict_is_valid(NX_X509_PUBKEY_EC_NOT_UNCOMPRESSED) != 1 { return 52 } 117 if nx_x509_pubkey_ec_verdict_is_valid(NX_X509_PUBKEY_EC_VERDICT_N) != 0 { return 53 } 118 if nx_x509_pubkey_ec_verdict_is_valid(0) != 0 { return 54 } 119 if nx_x509_pubkey_ec_verdict_is_valid(0 - 1) != 0 { return 55 } 120 if nx_x509_pubkey_ec_verdict_is_valid(999) != 0 { return 56 } 121 122 return 0 123}