Skip to content

Commit 86e32b5

Browse files
authored
more peer test (#191)
* update * update netaddr test * update peer test * update peer test * update test * update peer
1 parent 6b754db commit 86e32b5

File tree

9 files changed

+341
-23
lines changed

9 files changed

+341
-23
lines changed

Networking/Sources/CHelpers/helpers.c

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,89 @@
77

88
#include "helpers.h"
99

10+
int parse_certificate(
11+
const unsigned char *data,
12+
size_t length,
13+
unsigned char **public_key,
14+
size_t *public_key_len,
15+
char **alt_name,
16+
char **error_message)
17+
{
18+
int ret = -1;
19+
BIO *bio = NULL;
20+
X509 *cert = NULL;
21+
STACK_OF(GENERAL_NAME) *alt_names = NULL;
22+
23+
// Create BIO from certificate data
24+
bio = BIO_new_mem_buf(data, (int)length);
25+
if (!bio) {
26+
*error_message = "Failed to create BIO.";
27+
goto cleanup;
28+
}
29+
30+
// Parse the X509 certificate from the BIO
31+
cert = d2i_X509_bio(bio, NULL);
32+
if (!cert) {
33+
*error_message = "Failed to parse X509 certificate.";
34+
goto cleanup;
35+
}
36+
37+
// Extract the public key from the certificate
38+
EVP_PKEY *pkey = X509_get_pubkey(cert);
39+
if (!pkey) {
40+
*error_message = "Failed to get public key from certificate.";
41+
goto cleanup;
42+
}
43+
44+
// Get the raw public key
45+
if (EVP_PKEY_get_raw_public_key(pkey, NULL, public_key_len) <= 0) {
46+
*error_message = "Failed to get public key length.";
47+
goto cleanup;
48+
}
49+
*public_key = (unsigned char *)malloc(*public_key_len);
50+
if (!*public_key) {
51+
*error_message = "Failed to allocate memory for public key.";
52+
goto cleanup;
53+
}
54+
55+
if (EVP_PKEY_get_raw_public_key(pkey, *public_key, public_key_len) <= 0) {
56+
*error_message = "Failed to extract public key.";
57+
goto cleanup;
58+
}
59+
60+
// Extract the alternative name from the certificate (if present)
61+
alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
62+
if (alt_names) {
63+
for (int i = 0; i < sk_GENERAL_NAME_num(alt_names); i++) {
64+
GENERAL_NAME *gen_name = sk_GENERAL_NAME_value(alt_names, i);
65+
if (gen_name->type == GEN_DNS) {
66+
ASN1_STRING *name = gen_name->d.dNSName;
67+
*alt_name = strdup((char *)ASN1_STRING_get0_data(name));
68+
break;
69+
}
70+
}
71+
sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
72+
}
73+
74+
if (!*alt_name) {
75+
*error_message = "No alternative name found.";
76+
goto cleanup;
77+
}
78+
79+
ret = EXIT_SUCCESS; // Success
80+
81+
cleanup:
82+
if (ret != 0 && *public_key) {
83+
free(*public_key);
84+
*public_key = NULL;
85+
}
86+
BIO_free(bio);
87+
EVP_PKEY_free(pkey);
88+
X509_free(cert);
89+
90+
return ret;
91+
}
92+
1093
// Function to parse certificate and extract public key and alternative name
1194
int parse_pkcs12_certificate(
1295
const unsigned char *data,

Networking/Sources/CHelpers/helpers.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
#include <arpa/inet.h>
22
#include <stddef.h>
33

4+
int parse_certificate(
5+
const unsigned char *data,
6+
size_t length,
7+
unsigned char **public_key,
8+
size_t *public_key_len,
9+
char **alt_name,
10+
char **error_message);
11+
412
int parse_pkcs12_certificate(
513
const unsigned char *data,
614
size_t length,
@@ -21,4 +29,4 @@ char *get_error_string(int error);
2129
static inline uint16_t helper_ntohs(in_port_t netport)
2230
{
2331
return ntohs(netport);
24-
}
32+
}

Networking/Sources/MsQuicSwift/NetAddr.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ private func parseQuicAddr(_ addr: QUIC_ADDR) -> (String, UInt16, Bool)? {
104104
private func parseIpv4Addr(_ address: String) -> (String, UInt16)? {
105105
let ipv4Pattern =
106106
#"((?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"#
107-
let ipv4WithPortPattern = #"(\#(ipv4Pattern)):(\d{1,5})"#
107+
let ipv4WithPortPattern = #"(\#(ipv4Pattern)):(\d{1,5})(?=\s*$|\s+)"#
108108

109109
let regex = try? NSRegularExpression(pattern: ipv4WithPortPattern, options: [])
110110
let range = NSRange(location: 0, length: address.utf16.count)
@@ -142,7 +142,7 @@ private func parseIpv6Addr(_ address: String) -> (String, UInt16)? {
142142
"|(?:(?:[0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})?::",
143143
")",
144144
].reduce("", +)
145-
let ipv6WithPortPattern = #"\[(\#(ipv6Pattern))\]:(\d{1,5})"#
145+
let ipv6WithPortPattern = #"\[(\#(ipv6Pattern))\]:(\d{1,5})(?=\s*$|\s+)"#
146146

147147
let regex = try? NSRegularExpression(pattern: ipv6WithPortPattern, options: [])
148148
let range = NSRange(location: 0, length: address.utf16.count)

Networking/Sources/Networking/PKCS12.swift

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,45 @@ enum CryptoError: Error {
77
case parseFailed(String)
88
}
99

10-
public func parseCertificate(data: Data) throws -> (publicKey: Data, alternativeName: String) {
10+
public enum CertificateType {
11+
case x509
12+
case p12
13+
}
14+
15+
public func parseCertificate(data: Data, type: CertificateType) throws -> (
16+
publicKey: Data, alternativeName: String
17+
) {
1118
var publicKeyPointer: UnsafeMutablePointer<UInt8>!
1219
var publicKeyLen = 0
1320
var altNamePointer: UnsafeMutablePointer<Int8>!
1421
var errorMessage: UnsafeMutablePointer<Int8>?
1522
defer { free(altNamePointer) }
16-
let result = data.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) in
17-
parse_pkcs12_certificate(
18-
bytes.baseAddress!.assumingMemoryBound(to: UInt8.self),
19-
data.count,
20-
&publicKeyPointer,
21-
&publicKeyLen,
22-
&altNamePointer,
23-
&errorMessage
24-
)
25-
}
23+
24+
let result: Int32 =
25+
switch type {
26+
case .x509:
27+
data.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) in
28+
parse_certificate(
29+
bytes.baseAddress!.assumingMemoryBound(to: UInt8.self),
30+
data.count,
31+
&publicKeyPointer,
32+
&publicKeyLen,
33+
&altNamePointer,
34+
&errorMessage
35+
)
36+
}
37+
case .p12:
38+
data.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) in
39+
parse_pkcs12_certificate(
40+
bytes.baseAddress!.assumingMemoryBound(to: UInt8.self),
41+
data.count,
42+
&publicKeyPointer,
43+
&publicKeyLen,
44+
&altNamePointer,
45+
&errorMessage
46+
)
47+
}
48+
}
2649

2750
guard result == 0 else {
2851
throw CryptoError.parseFailed(String(cString: errorMessage!))

Networking/Sources/Networking/Peer.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ private struct PeerEventHandler<Handler: StreamHandler>: QuicEventHandler {
266266
return .code(.requiredCert)
267267
}
268268
do {
269-
let (publicKey, alternativeName) = try parseCertificate(data: certificate)
269+
let (publicKey, alternativeName) = try parseCertificate(data: certificate, type: .x509)
270270
logger.debug(
271271
"Certificate parsed",
272272
metadata: ["publicKey": "\(publicKey.toHexString())", "alternativeName": "\(alternativeName)"]
@@ -385,7 +385,7 @@ public final class MockPeerEventHandler: QuicEventHandler {
385385
return .code(.requiredCert)
386386
}
387387
do {
388-
let (publicKey, alternativeName) = try parseCertificate(data: certificate)
388+
let (publicKey, alternativeName) = try parseCertificate(data: certificate, type: .x509)
389389
if alternativeName != generateSubjectAlternativeName(pubkey: publicKey) {
390390
return .code(.badCert)
391391
}

Networking/Tests/MsQuicSwiftTests/NetAddrTests.swift

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,15 @@ struct NetAddrTests {
5151

5252
@Test
5353
func parseInvalidFormat() async throws {
54-
let address = "abcd:::"
55-
let netAddr = NetAddr(address: address)
56-
#expect(netAddr == nil)
54+
let address1 = "abcd:::"
55+
let netAddr1 = NetAddr(address: address1)
56+
#expect(netAddr1 == nil)
57+
let address2 = "127.0.0.1:12,awef"
58+
let netAddr2 = NetAddr(address: address2)
59+
#expect(netAddr2 == nil)
60+
let address3 = "[2001:db8:85a3::8a2e:370:7334]:8080,8081,8082"
61+
let netAddr3 = NetAddr(address: address3)
62+
#expect(netAddr3 == nil)
5763
}
5864

5965
@Test

Networking/Tests/NetworkingTests/PeerTest.swift renamed to Networking/Tests/NetworkingTests/MockPeerEventTests.swift

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import Utils
55

66
@testable import Networking
77

8-
final class PeerTests {
8+
final class MockPeerEventTests {
99
let registration: QuicRegistration
1010
let certData: Data
1111
let badCertData: Data
@@ -98,6 +98,66 @@ final class PeerTests {
9898
)
9999
}
100100

101+
@Test
102+
func connected() async throws {
103+
let serverHandler = MockPeerEventHandler()
104+
let clientHandler = MockPeerEventHandler()
105+
let privateKey1 = try Ed25519.SecretKey(from: Data32())
106+
let cert = try generateSelfSignedCertificate(privateKey: privateKey1)
107+
let serverConfiguration = try QuicConfiguration(
108+
registration: registration,
109+
pkcs12: certData,
110+
alpns: [Data("testalpn".utf8)],
111+
client: false,
112+
settings: QuicSettings.defaultSettings
113+
)
114+
115+
let listener = try QuicListener(
116+
handler: serverHandler,
117+
registration: registration,
118+
configuration: serverConfiguration,
119+
listenAddress: NetAddr(ipAddress: "127.0.0.1", port: 0)!,
120+
alpns: [Data("testalpn".utf8)]
121+
)
122+
123+
let listenAddress = try listener.listenAddress()
124+
// Client setup with certificate
125+
let clientConfiguration = try QuicConfiguration(
126+
registration: registration,
127+
pkcs12: cert,
128+
alpns: [Data("testalpn".utf8)],
129+
client: true,
130+
settings: QuicSettings.defaultSettings
131+
)
132+
133+
let clientConnection = try QuicConnection(
134+
handler: clientHandler,
135+
registration: registration,
136+
configuration: clientConfiguration
137+
)
138+
139+
// Attempt to connect
140+
try clientConnection.connect(to: listenAddress)
141+
let stream1 = try clientConnection.createStream()
142+
try stream1.send(data: Data("test data 1".utf8))
143+
144+
try? await Task.sleep(for: .milliseconds(100))
145+
let (_, info) = serverHandler.events.value.compactMap {
146+
switch $0 {
147+
case let .newConnection(_, connection, info):
148+
(connection, info) as (QuicConnection, ConnectionInfo)?
149+
default:
150+
nil
151+
}
152+
}.first!
153+
let (ipAddress2, _) = info.remoteAddress.getAddressAndPort()
154+
155+
#expect(info.negotiatedAlpn == Data("testalpn".utf8))
156+
#expect(info.serverName == "127.0.0.1")
157+
#expect(info.localAddress == listenAddress)
158+
#expect(ipAddress2 == "127.0.0.1")
159+
}
160+
101161
@Test
102162
func rejectsConDueToBadClientCert() async throws {
103163
let serverHandler = MockPeerEventHandler()

Networking/Tests/NetworkingTests/PKCS12Tests.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ import Utils
88
struct PKCS12Tests {
99
@Test func invalidParseCertificate() async throws {
1010
#expect(throws: CryptoError.self) {
11-
_ = try parseCertificate(data: Data("wrong cert data".utf8))
11+
_ = try parseCertificate(data: Data("wrong cert data".utf8), type: .p12)
1212
}
1313
}
1414

15-
@Test func vailidParseCertificate() async throws {
15+
@Test func vailidParseP12Certificate() async throws {
1616
let privateKey = try Ed25519.SecretKey(from: Data32())
1717
let cert = try generateSelfSignedCertificate(privateKey: privateKey)
18-
let (publicKey, alternativeName) = try parseCertificate(data: cert)
18+
let (publicKey, alternativeName) = try parseCertificate(data: cert, type: .p12)
1919
#expect(alternativeName == generateSubjectAlternativeName(publicKey: privateKey.publicKey))
2020
#expect(Data32(publicKey) == privateKey.publicKey.data)
2121
}

0 commit comments

Comments
 (0)