Skip to content

Commit 1fb088a

Browse files
ukellergrealish
authored andcommitted
MTLs working for HTTPS connections
1 parent 84bdb8d commit 1fb088a

File tree

18 files changed

+483
-141
lines changed

18 files changed

+483
-141
lines changed

parsec-client-java/src/main/java/org/parallaxsecond/parsec/client/core/BasicClient.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -454,9 +454,10 @@ public NativeResult.PingResult ping() {
454454
* Hash::Sha256.into(), }.into(), }, }; client.psa_generate_key("my_key", key_attrs); # Ok(())}
455455
* ```
456456
*/
457-
public void psaGenerateKey(String keyName, PsaKeyAttributes keyAttributes) {
457+
public void psaGenerateKey(String keyName, PsaKeyAttributes.KeyAttributes keyAttributes) {
458458
ProviderId cryptoProvider = this.canProvideCrypto();
459459

460+
460461
NativeResult res =
461462
this.operationClient.processOperation(
462463
NativeOperation.PsaGenerateKeyOperation.builder()

parsec-interface-java/src/main/java/org/parallaxsecond/parsec/protocol/operations/NativeOperation.java

+1-3
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,7 @@ class PsaGenerateKeyOperation implements NativeOperation {
7878
/** name must be unique per application. */
7979
String keyName;
8080
/** `attributes` specifies the parameters to be associated with the key. */
81-
// FIXME
82-
PsaKeyAttributes attributes;
81+
PsaKeyAttributes.KeyAttributes attributes;
8382
}
8483
/** PsaImportKey operation */
8584
@Value
@@ -92,7 +91,6 @@ class PsaImportKeyOperation implements NativeOperation {
9291
*/
9392
String keyName;
9493
/** `attributes` specifies the attributes for the new key. */
95-
// FIXME
9694
PsaKeyAttributes.KeyAttributes attributes;
9795
/**
9896
* `data` contains the bytes for the key, formatted in accordance with the requirements of the
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,45 @@
11
package org.parallaxsecond.parsec.protocol.operations_protobuf;
22

3+
import com.google.protobuf.InvalidProtocolBufferException;
4+
import org.parallaxsecond.parsec.protobuf.psa_generate_key.PsaGenerateKey;
35
import org.parallaxsecond.parsec.protocol.operations.NativeOperation;
46
import org.parallaxsecond.parsec.protocol.operations.NativeResult;
57
import org.parallaxsecond.parsec.protocol.requests.Opcode;
68
import org.parallaxsecond.parsec.protocol.requests.request.RequestBody;
79
import org.parallaxsecond.parsec.protocol.requests.response.ResponseBody;
8-
import com.google.protobuf.InvalidProtocolBufferException;
910

1011
public class PsaGenerateKeyProtobufOpConverter implements ProtobufOpConverter {
1112
@Override
12-
public NativeOperation bodyToOperation(RequestBody body, Opcode opcode) {
13-
throw new IllegalStateException("not implemented"); // FIXME
13+
public NativeOperation bodyToOperation(RequestBody body, Opcode opcode)
14+
throws InvalidProtocolBufferException {
15+
PsaGenerateKey.Operation protoBufOp = PsaGenerateKey.Operation.parseFrom(body.getBuffer());
16+
17+
return NativeOperation.PsaGenerateKeyOperation.builder()
18+
.keyName(protoBufOp.getKeyName())
19+
.attributes(protoBufOp.getAttributes())
20+
.build();
1421
}
1522

1623
@Override
1724
public RequestBody operationToBody(NativeOperation operation) {
18-
throw new IllegalStateException("not implemented"); // FIXME
25+
NativeOperation.PsaGenerateKeyOperation psaGenerateKeyOperation =
26+
(NativeOperation.PsaGenerateKeyOperation) operation;
27+
return new RequestBody(
28+
PsaGenerateKey.Operation.newBuilder()
29+
.setKeyName(psaGenerateKeyOperation.getKeyName())
30+
.setAttributes(psaGenerateKeyOperation.getAttributes())
31+
.build()
32+
.toByteArray());
1933
}
2034

2135
@Override
2236
public ResponseBody resultToBody(NativeResult result) {
23-
throw new IllegalStateException("not implemented"); // FIXME
37+
return new ResponseBody(PsaGenerateKey.Result.newBuilder().build().toByteArray());
2438
}
2539

2640
@Override
2741
public NativeResult tryBodyToResult(ResponseBody body, Opcode opcode)
2842
throws InvalidProtocolBufferException {
29-
throw new IllegalStateException("not implemented"); // FIXME
43+
return NativeResult.PsaGenerateKeyResult.builder().build();
3044
}
3145
}

parsec-jca-java-test/src/test/java/org/parallaxsecond/parsec/jce/provider/HttpClientTlsTest.java

+9-43
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
import org.apache.hc.client5.http.impl.classic.HttpClients;
99
import org.apache.hc.client5.http.impl.io.BasicHttpClientConnectionManager;
1010
import org.apache.hc.client5.http.socket.ConnectionSocketFactory;
11+
import org.apache.hc.client5.http.ssl.DefaultHostnameVerifier;
12+
import org.apache.hc.client5.http.ssl.HttpClientHostnameVerifier;
1113
import org.apache.hc.client5.http.ssl.NoopHostnameVerifier;
1214
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
1315
import org.apache.hc.core5.http.config.Registry;
@@ -93,47 +95,11 @@ private KeyManagerFactory prepareParsecTest() {
9395
client.psaImportKey(
9496
"client",
9597
Files.readAllBytes(clientKeyDer),
96-
PsaKeyAttributes.KeyAttributes.newBuilder()
97-
.setKeyPolicy(
98-
PsaKeyAttributes.KeyPolicy.newBuilder()
99-
100-
.setKeyAlgorithm(
101-
102-
PsaAlgorithm.Algorithm.newBuilder()
103-
104-
.setAsymmetricSignature(
105-
PsaAlgorithm.Algorithm
106-
.AsymmetricSignature
107-
.newBuilder()
108-
.setRsaPkcs1V15Sign(
109-
PsaAlgorithm.Algorithm.AsymmetricSignature.RsaPkcs1v15Sign.newBuilder()
110-
.setHashAlg(PsaAlgorithm.Algorithm.AsymmetricSignature.SignHash.newBuilder()
111-
.setAny(PsaAlgorithm.Algorithm.AsymmetricSignature.SignHash.Any.newBuilder().build())
112-
.build())
113-
.build()
114-
)
115-
.build())
116-
.build())
117-
.setKeyUsageFlags(
118-
PsaKeyAttributes.UsageFlags.newBuilder()
119-
.setDecrypt(true)
120-
.setEncrypt(true)
121-
.setSignMessage(true)
122-
.setVerifyMessage(true)
123-
.setVerifyHash(true)
124-
.setSignHash(true)
125-
.build())
126-
.build())
127-
.setKeyType(
128-
PsaKeyAttributes.KeyType.newBuilder()
129-
.setRsaKeyPair(
130-
PsaKeyAttributes.KeyType.RsaKeyPair.newBuilder()
131-
.build())
132-
.build())
133-
.build());
98+
ParsecCipherSuites.RSA_WITH_PKCS1.getKeyAttributes());
99+
134100
URI socketUri = parsecContainer.getSocketUri();
135101
Provider parsec = ParsecProvider.builder().socketUri(socketUri).build();
136-
Security.insertProviderAt(parsec, 1);
102+
Security.insertProviderAt(parsec, 0);
137103

138104
Path clientCertStoreFile = copyFromNginx("/keys/client_cert.jks");
139105
KeyStore clientCertStore = defaultKeystoreFromFile(clientCertStoreFile);
@@ -165,12 +131,11 @@ private String absFile(String f) {
165131
@SneakyThrows
166132
void setup() {
167133
Awaitility.await().until(nginxContainer::isRunning);
168-
hostPort = format("%s:%s", nginxContainer.getHost(), nginxContainer.getMappedPort(443));
169134
ExecResult r =
170135
nginxContainer.execInContainer(
171136
"sh",
172137
"-c",
173-
format("/init.sh %s %s /", hostPort, new String(keystorePassword)));
138+
format("/init.sh %s %s /", nginxContainer.getHost(), new String(keystorePassword)));
174139
assertEquals(0, r.getExitCode(), r.getStderr() + r.getStdout());
175140

176141
Path serverTrustStore = copyFromNginx("/keys/server_chain.jks");
@@ -215,15 +180,16 @@ void testHttpClient(String description, int expectedResponseCode, KmfTestFactory
215180
assertNotNull(sslContext.getProvider());
216181

217182
SSLConnectionSocketFactory sslsf =
218-
new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
183+
new SSLConnectionSocketFactory(sslContext, new DefaultHostnameVerifier());
219184

220185
Registry<ConnectionSocketFactory> socketFactoryRegistry =
221186
RegistryBuilder.<ConnectionSocketFactory>create().register("https", sslsf).build();
222187
BasicHttpClientConnectionManager connectionManager =
223188
new BasicHttpClientConnectionManager(socketFactoryRegistry);
224189
CloseableHttpClient httpClient =
225190
HttpClients.custom().setConnectionManager(connectionManager).build();
226-
CloseableHttpResponse r = httpClient.execute(new HttpGet("https://" + hostPort));
191+
CloseableHttpResponse r = httpClient.execute(
192+
new HttpGet(format("https://%s:%s", nginxContainer.getHost(), nginxContainer.getMappedPort(443))));
227193
assertEquals(expectedResponseCode, r.getCode());
228194
}
229195

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package org.parallaxsecond.parsec.jce.provider;
2+
3+
import lombok.SneakyThrows;
4+
import lombok.extern.slf4j.Slf4j;
5+
import org.junit.jupiter.api.Test;
6+
import org.parallaxsecond.parsec.client.core.BasicClient;
7+
import org.parallaxsecond.parsec.client.core.ipc_handler.IpcHandler;
8+
import org.parallaxsecond.testcontainers.ParsecContainer;
9+
import org.testcontainers.junit.jupiter.Container;
10+
import org.testcontainers.junit.jupiter.Testcontainers;
11+
12+
import java.io.File;
13+
import java.util.Random;
14+
15+
import static org.junit.jupiter.api.Assertions.assertTrue;
16+
import static org.parallaxsecond.parsec.jce.provider.ParsecCipherSuites.RSA_WITH_PKCS1;
17+
18+
@Testcontainers
19+
@Slf4j
20+
class ParsecSignatureTest {
21+
@Container
22+
ParsecContainer parsecContainer =
23+
ParsecContainer.withVersion("0.8.1")
24+
.withFileSystemBind(
25+
new File("src/test/resources/mbed-crypto-config.toml").getAbsolutePath(),
26+
"/etc/parsec/config.toml");
27+
28+
@SneakyThrows
29+
@Test
30+
void signVerify() {
31+
32+
byte[] payload = new byte[1024];
33+
new Random().nextBytes(payload);
34+
35+
String keyName="testSignVerify";
36+
37+
BasicClient client = BasicClient.client("parsec-tool", IpcHandler.connectFromUrl(parsecContainer.getSocketUri()));
38+
ParsecClientAccessor parsecClient= () -> client;
39+
ParsecSignatureInfo signatureInfo = ParsecRsaSignature.SHA256_WITH_RSA;
40+
41+
client.psaGenerateKey(keyName, RSA_WITH_PKCS1.getKeyAttributes());
42+
43+
ParsecRsaPrivateKey privKey = ParsecRsaPrivateKey.builder()
44+
45+
.parsecName(keyName)
46+
.algorithm("RSA")
47+
.format("RAW")
48+
.build();
49+
50+
51+
ParsecSignature signature = new ParsecSignature(signatureInfo, parsecClient);
52+
signature.engineInitSign(privKey);
53+
signature.engineUpdate(payload, 0, payload.length);
54+
byte[] signedBytes = signature.engineSign();
55+
56+
57+
ParsecPublicKey.ParsecPublicKeyImpl publicKey = ParsecPublicKey.builder()
58+
.parsecName(keyName)
59+
.build();
60+
61+
ParsecSignature verification = new ParsecSignature(signatureInfo, parsecClient);
62+
verification.engineInitVerify(publicKey);
63+
verification.engineUpdate(payload, 0, payload.length);
64+
assertTrue(verification.engineVerify(signedBytes));
65+
66+
67+
}
68+
69+
}

parsec-jca-java-test/src/test/resources/nginx-client-auth/init.sh

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/bin/bash -e
22
# script runs on nginx after ports and hosts are known
33

4-
HOST_PORT="$1"
4+
HOST="$1"
55
PASSWORD="$2"
66
ROOT="${3:-.}"
77

@@ -73,7 +73,7 @@ subjectAltName = $ALTNAMES
7373
EOF
7474

7575
cat >server.cnf << EOF
76-
FQDN = $HOST_PORT
76+
FQDN = $HOST
7777
ORGNAME = ParsecTest
7878
ALTNAMES = DNS:\$FQDN # , DNS:bar.example.org , DNS:www.foo.example.org
7979
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package org.parallaxsecond.parsec.jce.provider;
2+
3+
import lombok.Getter;
4+
import lombok.Setter;
5+
import lombok.experimental.Delegate;
6+
7+
import java.nio.ByteBuffer;
8+
9+
public final class DynamicByteBuffer implements DynamicByteBufferWriter {
10+
@Getter
11+
@Setter
12+
@Delegate(excludes = DynamicByteBufferWriter.class)
13+
private ByteBuffer byteBuffer;
14+
@Getter private final float growFactor;
15+
public DynamicByteBuffer(int initialCapacity, float growFactor) {
16+
if (growFactor <= 1) {
17+
throw new IllegalArgumentException("growFactor must be > 1");
18+
}
19+
this.growFactor = growFactor;
20+
this.byteBuffer = ByteBuffer.allocate(initialCapacity);
21+
}
22+
}

0 commit comments

Comments
 (0)