You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@mina.apache.org by "etnt (via GitHub)" <gi...@apache.org> on 2026/10/19 11:42:00 UTC

[PR] GH-928: Add OQS-OpenSSH test image for pure ML-KEM and ML-DSA interoperability [mina-sshd]

etnt opened a new pull request, #931:
URL: https://github.com/apache/mina-sshd/pull/931

   Add a small multi-arch (amd64, arm64) Docker image that runs the Open Quantum Safe fork of OpenSSH. It offers the pure ML-KEM key exchanges mlkem512-sha256, mlkem768-sha256 and mlkem1024-sha384, and pure ML-DSA host and user keys (ssh-mldsa-44/65/87), so that MINA SSHD can be tested against a third-party implementation.
   
   The image pins the Alpine base image by digest and liboqs by commit. Include a smoke test and a workflow that builds the image on native amd64 and arm64 runners, smoke-tests it, and publishes it to ghcr.io. The Maven build workflows ignore changes to docker/ and the image workflow.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@mina.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@mina.apache.org
For additional commands, e-mail: dev-help@mina.apache.org


Re: [PR] GH-928: Add OQS-OpenSSH test image for pure ML-KEM and ML-DSA interoperability [mina-sshd]

Posted by "etnt (via GitHub)" <gi...@apache.org>.
etnt commented on code in PR #931:
URL: https://github.com/apache/mina-sshd/pull/931#discussion_r4314107703


##########
docker/oqs-openssh/entrypoint.sh:
##########
@@ -0,0 +1,27 @@
+#!/bin/sh
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Generate host keys on first start, set the test user password, run sshd.
+set -e
+K=/etc/ssh
+[ -f $K/ssh_host_ed25519_key ] || ssh-keygen -q -t ed25519    -N '' -f $K/ssh_host_ed25519_key
+[ -f $K/ssh_host_mldsa44_key ] || ssh-keygen -q -t ssh-mldsa-44 -N '' -f $K/ssh_host_mldsa44_key
+[ -f $K/ssh_host_mldsa65_key ] || ssh-keygen -q -t ssh-mldsa-65 -N '' -f $K/ssh_host_mldsa65_key
+[ -f $K/ssh_host_mldsa87_key ] || ssh-keygen -q -t ssh-mldsa-87 -N '' -f $K/ssh_host_mldsa87_key

Review Comment:
   fixed



##########
docker/oqs-openssh/sshd_config:
##########
@@ -0,0 +1,33 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Test server configuration. Only pure PQC algorithms for key exchange.
+Port 22
+HostKey /etc/ssh/ssh_host_mldsa44_key
+HostKey /etc/ssh/ssh_host_mldsa65_key
+HostKey /etc/ssh/ssh_host_mldsa87_key
+HostKey /etc/ssh/ssh_host_ed25519_key
+
+KexAlgorithms mlkem768-sha256,mlkem1024-sha384,mlkem512-sha256
+HostKeyAlgorithms ssh-mldsa-44,ssh-mldsa-65,ssh-mldsa-87,ssh-ed25519
+PubkeyAcceptedAlgorithms ssh-mldsa-44,ssh-mldsa-65,ssh-mldsa-87,ssh-ed25519
+
+PasswordAuthentication yes
+PubkeyAuthentication yes
+PermitRootLogin no

Review Comment:
   fixed



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@mina.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@mina.apache.org
For additional commands, e-mail: dev-help@mina.apache.org


Re: [PR] GH-928: Add OQS-OpenSSH test image for pure ML-KEM and ML-DSA interoperability [mina-sshd]

Posted by "Copilot (via GitHub)" <gi...@apache.org>.
Copilot commented on code in PR #931:
URL: https://github.com/apache/mina-sshd/pull/931#discussion_r4314279457


##########
.github/workflows/oqs-openssh-image.yml:
##########
@@ -0,0 +1,135 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Builds the multi-arch OQS-OpenSSH test image (GH-928), smoke-tests it on each
+# architecture, and publishes it to GitHub Container Registry.
+
+name: oqs-openssh-image
+
+on:
+  workflow_dispatch:
+    inputs:
+      tag:
+        description: 'Image tag'
+        default: 'dev'
+  push:
+    paths:
+      - 'docker/oqs-openssh/**'
+      - '.github/workflows/oqs-openssh-image.yml'
+
+env:
+  CONTEXT: docker/oqs-openssh
+  TAG: ${{ inputs.tag || 'dev' }}

Review Comment:
   `inputs.tag` is not available for `push` events in GitHub Actions, which can cause workflow evaluation to fail. Use `github.event.inputs.tag` for `workflow_dispatch`, or gate it on `github.event_name` (e.g., `github.event_name == 'workflow_dispatch' && github.event.inputs.tag || 'dev'`).



##########
docker/oqs-openssh/smoke-test.sh:
##########
@@ -0,0 +1,59 @@
+#!/bin/sh
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Smoke test for the OQS-OpenSSH test image.
+# Usage: smoke-test.sh <image> [docker|podman]
+# Checks that pure ML-KEM and pure ML-DSA work in a real connection.
+set -eu
+IMAGE=${1:?usage: smoke-test.sh <image> [docker|podman]}
+CT=${2:-docker}
+NAME=oqs-smoke-$$
+trap '$CT rm -f "$NAME" >/dev/null 2>&1 || true' EXIT
+
+$CT run -d --name "$NAME" "$IMAGE" >/dev/null
+# Wait for sshd (host key generation happens at start).
+i=0
+until $CT logs "$NAME" 2>&1 | grep -q "Server listening"; do
+    i=$((i + 1)); [ $i -gt 60 ] && { echo "sshd did not start"; $CT logs "$NAME"; exit 1; }
+    sleep 1
+done
+
+ctr() { $CT exec "$NAME" sh -c "$1"; }
+
+echo "== architecture: $(ctr 'uname -m')"
+ctr 'ssh -Q kex' | grep -qx mlkem768-sha256 && echo "OK kex mlkem768-sha256"
+ctr 'ssh -Q kex' | grep -qx mlkem1024-sha384 && echo "OK kex mlkem1024-sha384"
+for k in ssh-mldsa-44 ssh-mldsa-65 ssh-mldsa-87; do
+    ctr 'ssh -Q key' | grep -qx "$k" && echo "OK key $k"

Review Comment:
   With `set -e`, these checks will terminate the script on failure but without a clear failure message for which algorithm was missing. Consider mirroring the later pattern (`|| { echo \"FAIL ...\"; ...; exit 1; }`) to make CI failures easier to diagnose.



##########
docker/oqs-openssh/Dockerfile:
##########
@@ -0,0 +1,85 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Small, multi-arch (linux/amd64, linux/arm64) OpenSSH server with PURE ML-KEM
+# key exchange (mlkem768-sha256, ...) and pure ML-DSA host/user keys
+# (ssh-mldsa-44/65/87), for MINA SSHD interoperability tests (GH-928).
+#
+# Based on the Open Quantum Safe OpenSSH fork (branch OQS-v10, OpenSSH 10.3p1).
+# Everything is compiled in the BUILD stage. The final image only has the
+# runtime files, so tests pull a small prebuilt image and need no compiler.
+#
+# Build:   docker buildx build --platform linux/amd64,linux/arm64 -t <name> .
+# Run:     docker run --rm -p 2222:22 <name>
+
+# Alpine 3.22.6 multi-arch index (includes linux/amd64 and linux/arm64).
+# The digest wins over the tag; update the digest to change the base image.
+FROM alpine:3.22.6@sha256:5291449c3df73caf6ed85e649dec1b9e818b39a5d8c871e97afc13e9cd5e8fa8 AS build
+# Pinned versions. Change them together and re-run the interop tests.
+# LIBOQS_REF is the commit of the 0.16.0 tag.
+ARG LIBOQS_REF=5a1a854b0dc9f2141bdc771c555ee60c37950183
+ARG OQS_OPENSSH_REF=10d74f8b27da43705cfab85923ac7e1d769416f1
+RUN apk add --no-cache build-base cmake ninja git autoconf automake \
+        openssl-dev zlib-dev linux-headers
+WORKDIR /src
+
+# liboqs. Do NOT use OQS_MINIMAL_BUILD: ssh-oqs.c references many signature
+# algorithms (mayo, ...), so the fork does not compile against a trimmed liboqs.
+RUN git init liboqs \
+ && git -C liboqs fetch --depth 1 https://github.com/open-quantum-safe/liboqs.git "${LIBOQS_REF}" \
+ && git -C liboqs checkout FETCH_HEAD \
+ && cmake -S liboqs -B liboqs/build -GNinja \
+        -DCMAKE_BUILD_TYPE=Release \
+        -DBUILD_SHARED_LIBS=ON \
+        -DCMAKE_INSTALL_PREFIX=/opt/oqs \
+        -DOQS_BUILD_ONLY_LIB=ON \
+        -DOQS_DIST_BUILD=ON \
+        -DOQS_USE_OPENSSL=ON \
+ && cmake --build liboqs/build \
+ && cmake --install liboqs/build
+
+# OQS-OpenSSH, installed under /opt/ssh.
+# The fork calls sshkey_clear_pkey() without a visible prototype (an upstream
+# header quirk). Its own CI hides this with -Wno-implicit-function-declaration;
+# GCC 14 (Alpine 3.22) needs the "-Wno-error=" form.
+RUN git clone https://github.com/open-quantum-safe/openssh.git openssh \
+ && git -C openssh checkout "${OQS_OPENSSH_REF}" \

Review Comment:
   This `git clone` pulls full history by default, which can significantly slow image builds on CI and increase network usage. Consider switching to the same pattern used for `liboqs` (init + depth-1 fetch of the pinned commit) or `git clone --depth 1` plus a fetch of the specific ref as needed.



##########
docker/oqs-openssh/smoke-test.sh:
##########
@@ -0,0 +1,59 @@
+#!/bin/sh
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Smoke test for the OQS-OpenSSH test image.
+# Usage: smoke-test.sh <image> [docker|podman]
+# Checks that pure ML-KEM and pure ML-DSA work in a real connection.
+set -eu
+IMAGE=${1:?usage: smoke-test.sh <image> [docker|podman]}
+CT=${2:-docker}
+NAME=oqs-smoke-$$
+trap '$CT rm -f "$NAME" >/dev/null 2>&1 || true' EXIT
+
+$CT run -d --name "$NAME" "$IMAGE" >/dev/null
+# Wait for sshd (host key generation happens at start).
+i=0
+until $CT logs "$NAME" 2>&1 | grep -q "Server listening"; do
+    i=$((i + 1)); [ $i -gt 60 ] && { echo "sshd did not start"; $CT logs "$NAME"; exit 1; }
+    sleep 1
+done
+
+ctr() { $CT exec "$NAME" sh -c "$1"; }
+
+echo "== architecture: $(ctr 'uname -m')"
+ctr 'ssh -Q kex' | grep -qx mlkem768-sha256 && echo "OK kex mlkem768-sha256"
+ctr 'ssh -Q kex' | grep -qx mlkem1024-sha384 && echo "OK kex mlkem1024-sha384"
+for k in ssh-mldsa-44 ssh-mldsa-65 ssh-mldsa-87; do
+    ctr 'ssh -Q key' | grep -qx "$k" && echo "OK key $k"
+done
+
+ctr 'su test -c "ssh-keygen -q -t ssh-mldsa-44 -N \"\" -f ~/.ssh/id \
+   && cp ~/.ssh/id.pub ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"'
+
+for kex in mlkem512-sha256 mlkem768-sha256 mlkem1024-sha384; do
+  for hk in ssh-mldsa-44 ssh-mldsa-65 ssh-mldsa-87; do
+    out=$(ctr "su test -c 'ssh -v -o StrictHostKeyChecking=no -o KexAlgorithms=$kex \
+        -o HostKeyAlgorithms=$hk -o PubkeyAcceptedAlgorithms=ssh-mldsa-44 -i ~/.ssh/id \

Review Comment:
   The identity file is specified as `-i ~/.ssh/id` inside a single-quoted `sh -c` string; depending on how the client processes the `-i` value, `~` may not expand, causing authentication failures. Prefer an explicit absolute path (e.g., `/home/test/.ssh/id`) in the smoke test for determinism.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@mina.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@mina.apache.org
For additional commands, e-mail: dev-help@mina.apache.org


Re: [PR] GH-928: Add OQS-OpenSSH test image for pure ML-KEM and ML-DSA interoperability [mina-sshd]

Posted by "etnt (via GitHub)" <gi...@apache.org>.
etnt commented on code in PR #931:
URL: https://github.com/apache/mina-sshd/pull/931#discussion_r4314103467


##########
docker/oqs-openssh/entrypoint.sh:
##########
@@ -0,0 +1,27 @@
+#!/bin/sh
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Generate host keys on first start, set the test user password, run sshd.
+set -e
+K=/etc/ssh
+[ -f $K/ssh_host_ed25519_key ] || ssh-keygen -q -t ed25519    -N '' -f $K/ssh_host_ed25519_key
+[ -f $K/ssh_host_mldsa44_key ] || ssh-keygen -q -t ssh-mldsa-44 -N '' -f $K/ssh_host_mldsa44_key
+[ -f $K/ssh_host_mldsa65_key ] || ssh-keygen -q -t ssh-mldsa-65 -N '' -f $K/ssh_host_mldsa65_key
+[ -f $K/ssh_host_mldsa87_key ] || ssh-keygen -q -t ssh-mldsa-87 -N '' -f $K/ssh_host_mldsa87_key
+echo "test:${TEST_PASSWORD:-test}" | chpasswd

Review Comment:
   fixed!



##########
docker/oqs-openssh/Dockerfile:
##########
@@ -0,0 +1,86 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Small, multi-arch (linux/amd64, linux/arm64) OpenSSH server with PURE ML-KEM
+# key exchange (mlkem768-sha256, ...) and pure ML-DSA host/user keys
+# (ssh-mldsa-44/65/87), for MINA SSHD interoperability tests (GH-928).
+#
+# Based on the Open Quantum Safe OpenSSH fork (branch OQS-v10, OpenSSH 10.3p1).
+# Everything is compiled in the BUILD stage. The final image only has the
+# runtime files, so tests pull a small prebuilt image and need no compiler.
+#
+# Build:   docker buildx build --platform linux/amd64,linux/arm64 -t <name> .
+# Run:     docker run --rm -p 2222:22 <name>
+
+# Alpine 3.22.6 multi-arch index (includes linux/amd64 and linux/arm64).
+# The digest wins over the tag; update the digest to change the base image.
+FROM alpine:3.22.6@sha256:5291449c3df73caf6ed85e649dec1b9e818b39a5d8c871e97afc13e9cd5e8fa8 AS build
+# Pinned versions. Change them together and re-run the interop tests.
+# LIBOQS_REF is the commit of the 0.16.0 tag.
+ARG LIBOQS_REF=5a1a854b0dc9f2141bdc771c555ee60c37950183
+ARG OQS_OPENSSH_REF=10d74f8b27da43705cfab85923ac7e1d769416f1
+RUN apk add --no-cache build-base cmake ninja git autoconf automake \
+        openssl-dev zlib-dev linux-headers
+WORKDIR /src
+
+# liboqs. Do NOT use OQS_MINIMAL_BUILD: ssh-oqs.c references many signature
+# algorithms (mayo, ...), so the fork does not compile against a trimmed liboqs.
+RUN git init liboqs \
+ && git -C liboqs fetch --depth 1 https://github.com/open-quantum-safe/liboqs.git "${LIBOQS_REF}" \
+ && git -C liboqs checkout FETCH_HEAD \
+ && cmake -S liboqs -B liboqs/build -GNinja \
+        -DCMAKE_BUILD_TYPE=Release \
+        -DBUILD_SHARED_LIBS=ON \
+        -DCMAKE_INSTALL_PREFIX=/opt/oqs \
+        -DOQS_BUILD_ONLY_LIB=ON \
+        -DOQS_DIST_BUILD=ON \
+        -DOQS_USE_OPENSSL=ON \
+ && cmake --build liboqs/build \
+ && cmake --install liboqs/build
+
+# OQS-OpenSSH, installed under /opt/ssh.
+# The fork calls sshkey_clear_pkey() without a visible prototype (an upstream
+# header quirk). Its own CI hides this with -Wno-implicit-function-declaration;
+# GCC 14 (Alpine 3.22) needs the "-Wno-error=" form.
+RUN git clone https://github.com/open-quantum-safe/openssh.git openssh \
+ && git -C openssh checkout "${OQS_OPENSSH_REF}" \
+ && cd openssh \
+ && autoreconf -i \
+ && ./configure --prefix=/opt/ssh --sysconfdir=/etc/ssh \
+        --with-ssl-dir=/usr --with-liboqs-dir=/opt/oqs \
+        --with-ldflags="-Wl,-rpath,/opt/oqs/lib" --with-libs=-lm \
+        --with-cflags="-Wno-error=implicit-function-declaration" \
+        --without-pam --without-selinux --with-privsep-path=/var/empty \
+ && make -j"$(nproc)" \
+ && make install-nokeys \
+ && strip /opt/ssh/sbin/sshd /opt/ssh/bin/ssh /opt/ssh/bin/ssh-keygen
+
+FROM alpine:3.22.6@sha256:5291449c3df73caf6ed85e649dec1b9e818b39a5d8c871e97afc13e9cd5e8fa8
+RUN apk add --no-cache libcrypto3 zlib \
+ && addgroup -S sshd 2>/dev/null; adduser -S -D -H -h /var/empty -s /sbin/nologin -G sshd sshd 2>/dev/null; \
+    adduser -D -s /bin/sh test \

Review Comment:
   fixed



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@mina.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@mina.apache.org
For additional commands, e-mail: dev-help@mina.apache.org


Re: [PR] GH-928: Add OQS-OpenSSH test image for pure ML-KEM and ML-DSA interoperability [mina-sshd]

Posted by "etnt (via GitHub)" <gi...@apache.org>.
etnt commented on code in PR #931:
URL: https://github.com/apache/mina-sshd/pull/931#discussion_r4314553955


##########
docker/oqs-openssh/smoke-test.sh:
##########
@@ -0,0 +1,59 @@
+#!/bin/sh
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Smoke test for the OQS-OpenSSH test image.
+# Usage: smoke-test.sh <image> [docker|podman]
+# Checks that pure ML-KEM and pure ML-DSA work in a real connection.
+set -eu
+IMAGE=${1:?usage: smoke-test.sh <image> [docker|podman]}
+CT=${2:-docker}
+NAME=oqs-smoke-$$
+trap '$CT rm -f "$NAME" >/dev/null 2>&1 || true' EXIT
+
+$CT run -d --name "$NAME" "$IMAGE" >/dev/null
+# Wait for sshd (host key generation happens at start).
+i=0
+until $CT logs "$NAME" 2>&1 | grep -q "Server listening"; do
+    i=$((i + 1)); [ $i -gt 60 ] && { echo "sshd did not start"; $CT logs "$NAME"; exit 1; }
+    sleep 1
+done
+
+ctr() { $CT exec "$NAME" sh -c "$1"; }
+
+echo "== architecture: $(ctr 'uname -m')"
+ctr 'ssh -Q kex' | grep -qx mlkem768-sha256 && echo "OK kex mlkem768-sha256"
+ctr 'ssh -Q kex' | grep -qx mlkem1024-sha384 && echo "OK kex mlkem1024-sha384"
+for k in ssh-mldsa-44 ssh-mldsa-65 ssh-mldsa-87; do
+    ctr 'ssh -Q key' | grep -qx "$k" && echo "OK key $k"

Review Comment:
   fixed



##########
docker/oqs-openssh/smoke-test.sh:
##########
@@ -0,0 +1,59 @@
+#!/bin/sh
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Smoke test for the OQS-OpenSSH test image.
+# Usage: smoke-test.sh <image> [docker|podman]
+# Checks that pure ML-KEM and pure ML-DSA work in a real connection.
+set -eu
+IMAGE=${1:?usage: smoke-test.sh <image> [docker|podman]}
+CT=${2:-docker}
+NAME=oqs-smoke-$$
+trap '$CT rm -f "$NAME" >/dev/null 2>&1 || true' EXIT
+
+$CT run -d --name "$NAME" "$IMAGE" >/dev/null
+# Wait for sshd (host key generation happens at start).
+i=0
+until $CT logs "$NAME" 2>&1 | grep -q "Server listening"; do
+    i=$((i + 1)); [ $i -gt 60 ] && { echo "sshd did not start"; $CT logs "$NAME"; exit 1; }
+    sleep 1
+done
+
+ctr() { $CT exec "$NAME" sh -c "$1"; }
+
+echo "== architecture: $(ctr 'uname -m')"
+ctr 'ssh -Q kex' | grep -qx mlkem768-sha256 && echo "OK kex mlkem768-sha256"
+ctr 'ssh -Q kex' | grep -qx mlkem1024-sha384 && echo "OK kex mlkem1024-sha384"
+for k in ssh-mldsa-44 ssh-mldsa-65 ssh-mldsa-87; do
+    ctr 'ssh -Q key' | grep -qx "$k" && echo "OK key $k"
+done
+
+ctr 'su test -c "ssh-keygen -q -t ssh-mldsa-44 -N \"\" -f ~/.ssh/id \
+   && cp ~/.ssh/id.pub ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"'
+
+for kex in mlkem512-sha256 mlkem768-sha256 mlkem1024-sha384; do
+  for hk in ssh-mldsa-44 ssh-mldsa-65 ssh-mldsa-87; do
+    out=$(ctr "su test -c 'ssh -v -o StrictHostKeyChecking=no -o KexAlgorithms=$kex \
+        -o HostKeyAlgorithms=$hk -o PubkeyAcceptedAlgorithms=ssh-mldsa-44 -i ~/.ssh/id \

Review Comment:
   fixed



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@mina.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@mina.apache.org
For additional commands, e-mail: dev-help@mina.apache.org


Re: [PR] GH-928: Add OQS-OpenSSH test image for pure ML-KEM and ML-DSA interoperability [mina-sshd]

Posted by "Copilot (via GitHub)" <gi...@apache.org>.
Copilot commented on code in PR #931:
URL: https://github.com/apache/mina-sshd/pull/931#discussion_r4313531346


##########
docker/oqs-openssh/sshd_config:
##########
@@ -0,0 +1,33 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Test server configuration. Only pure PQC algorithms for key exchange.
+Port 22
+HostKey /etc/ssh/ssh_host_mldsa44_key
+HostKey /etc/ssh/ssh_host_mldsa65_key
+HostKey /etc/ssh/ssh_host_mldsa87_key
+HostKey /etc/ssh/ssh_host_ed25519_key
+
+KexAlgorithms mlkem768-sha256,mlkem1024-sha384,mlkem512-sha256
+HostKeyAlgorithms ssh-mldsa-44,ssh-mldsa-65,ssh-mldsa-87,ssh-ed25519
+PubkeyAcceptedAlgorithms ssh-mldsa-44,ssh-mldsa-65,ssh-mldsa-87,ssh-ed25519
+
+PasswordAuthentication yes
+PubkeyAuthentication yes
+PermitRootLogin no

Review Comment:
   Enabling `PasswordAuthentication yes` combined with the entrypoint’s default `test` password makes the published image insecure-by-default if anyone runs it with an exposed port (intentionally or accidentally). Since the smoke test uses public keys anyway, consider setting `PasswordAuthentication no` by default and only enabling it explicitly (e.g., via a separate env flag that the entrypoint converts to `sshd -o PasswordAuthentication=yes`, or by requiring `TEST_PASSWORD` to be set to a non-default value before enabling password auth).



##########
docker/oqs-openssh/entrypoint.sh:
##########
@@ -0,0 +1,27 @@
+#!/bin/sh
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Generate host keys on first start, set the test user password, run sshd.
+set -e
+K=/etc/ssh
+[ -f $K/ssh_host_ed25519_key ] || ssh-keygen -q -t ed25519    -N '' -f $K/ssh_host_ed25519_key
+[ -f $K/ssh_host_mldsa44_key ] || ssh-keygen -q -t ssh-mldsa-44 -N '' -f $K/ssh_host_mldsa44_key
+[ -f $K/ssh_host_mldsa65_key ] || ssh-keygen -q -t ssh-mldsa-65 -N '' -f $K/ssh_host_mldsa65_key
+[ -f $K/ssh_host_mldsa87_key ] || ssh-keygen -q -t ssh-mldsa-87 -N '' -f $K/ssh_host_mldsa87_key
+echo "test:${TEST_PASSWORD:-test}" | chpasswd

Review Comment:
   `TEST_PASSWORD` is interpolated directly into `chpasswd` input. If it contains a newline, an attacker (or accidental value) could inject additional `user:password` lines and potentially set passwords for other accounts (e.g., `root`). Use `printf` with a fixed username and reject/strip `:` and newline characters in `TEST_PASSWORD` (fail fast if present) before passing it to `chpasswd`.



##########
docker/oqs-openssh/Dockerfile:
##########
@@ -0,0 +1,86 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Small, multi-arch (linux/amd64, linux/arm64) OpenSSH server with PURE ML-KEM
+# key exchange (mlkem768-sha256, ...) and pure ML-DSA host/user keys
+# (ssh-mldsa-44/65/87), for MINA SSHD interoperability tests (GH-928).
+#
+# Based on the Open Quantum Safe OpenSSH fork (branch OQS-v10, OpenSSH 10.3p1).
+# Everything is compiled in the BUILD stage. The final image only has the
+# runtime files, so tests pull a small prebuilt image and need no compiler.
+#
+# Build:   docker buildx build --platform linux/amd64,linux/arm64 -t <name> .
+# Run:     docker run --rm -p 2222:22 <name>
+
+# Alpine 3.22.6 multi-arch index (includes linux/amd64 and linux/arm64).
+# The digest wins over the tag; update the digest to change the base image.
+FROM alpine:3.22.6@sha256:5291449c3df73caf6ed85e649dec1b9e818b39a5d8c871e97afc13e9cd5e8fa8 AS build
+# Pinned versions. Change them together and re-run the interop tests.
+# LIBOQS_REF is the commit of the 0.16.0 tag.
+ARG LIBOQS_REF=5a1a854b0dc9f2141bdc771c555ee60c37950183
+ARG OQS_OPENSSH_REF=10d74f8b27da43705cfab85923ac7e1d769416f1
+RUN apk add --no-cache build-base cmake ninja git autoconf automake \
+        openssl-dev zlib-dev linux-headers
+WORKDIR /src
+
+# liboqs. Do NOT use OQS_MINIMAL_BUILD: ssh-oqs.c references many signature
+# algorithms (mayo, ...), so the fork does not compile against a trimmed liboqs.
+RUN git init liboqs \
+ && git -C liboqs fetch --depth 1 https://github.com/open-quantum-safe/liboqs.git "${LIBOQS_REF}" \
+ && git -C liboqs checkout FETCH_HEAD \
+ && cmake -S liboqs -B liboqs/build -GNinja \
+        -DCMAKE_BUILD_TYPE=Release \
+        -DBUILD_SHARED_LIBS=ON \
+        -DCMAKE_INSTALL_PREFIX=/opt/oqs \
+        -DOQS_BUILD_ONLY_LIB=ON \
+        -DOQS_DIST_BUILD=ON \
+        -DOQS_USE_OPENSSL=ON \
+ && cmake --build liboqs/build \
+ && cmake --install liboqs/build
+
+# OQS-OpenSSH, installed under /opt/ssh.
+# The fork calls sshkey_clear_pkey() without a visible prototype (an upstream
+# header quirk). Its own CI hides this with -Wno-implicit-function-declaration;
+# GCC 14 (Alpine 3.22) needs the "-Wno-error=" form.
+RUN git clone https://github.com/open-quantum-safe/openssh.git openssh \
+ && git -C openssh checkout "${OQS_OPENSSH_REF}" \
+ && cd openssh \
+ && autoreconf -i \
+ && ./configure --prefix=/opt/ssh --sysconfdir=/etc/ssh \
+        --with-ssl-dir=/usr --with-liboqs-dir=/opt/oqs \
+        --with-ldflags="-Wl,-rpath,/opt/oqs/lib" --with-libs=-lm \
+        --with-cflags="-Wno-error=implicit-function-declaration" \
+        --without-pam --without-selinux --with-privsep-path=/var/empty \
+ && make -j"$(nproc)" \
+ && make install-nokeys \
+ && strip /opt/ssh/sbin/sshd /opt/ssh/bin/ssh /opt/ssh/bin/ssh-keygen
+
+FROM alpine:3.22.6@sha256:5291449c3df73caf6ed85e649dec1b9e818b39a5d8c871e97afc13e9cd5e8fa8
+RUN apk add --no-cache libcrypto3 zlib \
+ && addgroup -S sshd 2>/dev/null; adduser -S -D -H -h /var/empty -s /sbin/nologin -G sshd sshd 2>/dev/null; \
+    adduser -D -s /bin/sh test \

Review Comment:
   This `RUN` mixes `&&` with `;`, which can mask failures: if `addgroup` or the first `adduser` fails, the shell will still continue after `;` and the overall layer exit status will be determined by the last command. Prefer chaining with `&&` throughout, and if the intent is to ignore 'already exists' errors, make that explicit (e.g., `... || true`) so unexpected failures don’t get swallowed.



##########
docker/oqs-openssh/entrypoint.sh:
##########
@@ -0,0 +1,27 @@
+#!/bin/sh
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Generate host keys on first start, set the test user password, run sshd.
+set -e
+K=/etc/ssh
+[ -f $K/ssh_host_ed25519_key ] || ssh-keygen -q -t ed25519    -N '' -f $K/ssh_host_ed25519_key
+[ -f $K/ssh_host_mldsa44_key ] || ssh-keygen -q -t ssh-mldsa-44 -N '' -f $K/ssh_host_mldsa44_key
+[ -f $K/ssh_host_mldsa65_key ] || ssh-keygen -q -t ssh-mldsa-65 -N '' -f $K/ssh_host_mldsa65_key
+[ -f $K/ssh_host_mldsa87_key ] || ssh-keygen -q -t ssh-mldsa-87 -N '' -f $K/ssh_host_mldsa87_key

Review Comment:
   The variable-expanded paths aren’t quoted. While `/etc/ssh` is stable, quoting (`\"$K/...\"`) avoids word-splitting/globbing hazards and aligns with standard shell scripting practices (also makes ShellCheck happy).



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@mina.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@mina.apache.org
For additional commands, e-mail: dev-help@mina.apache.org


Re: [PR] GH-928: Add OQS-OpenSSH test image for pure ML-KEM and ML-DSA interoperability [mina-sshd]

Posted by "etnt (via GitHub)" <gi...@apache.org>.
etnt commented on code in PR #931:
URL: https://github.com/apache/mina-sshd/pull/931#discussion_r4314550623


##########
.github/workflows/oqs-openssh-image.yml:
##########
@@ -0,0 +1,135 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Builds the multi-arch OQS-OpenSSH test image (GH-928), smoke-tests it on each
+# architecture, and publishes it to GitHub Container Registry.
+
+name: oqs-openssh-image
+
+on:
+  workflow_dispatch:
+    inputs:
+      tag:
+        description: 'Image tag'
+        default: 'dev'
+  push:
+    paths:
+      - 'docker/oqs-openssh/**'
+      - '.github/workflows/oqs-openssh-image.yml'
+
+env:
+  CONTEXT: docker/oqs-openssh
+  TAG: ${{ inputs.tag || 'dev' }}

Review Comment:
   fixed



##########
docker/oqs-openssh/Dockerfile:
##########
@@ -0,0 +1,85 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Small, multi-arch (linux/amd64, linux/arm64) OpenSSH server with PURE ML-KEM
+# key exchange (mlkem768-sha256, ...) and pure ML-DSA host/user keys
+# (ssh-mldsa-44/65/87), for MINA SSHD interoperability tests (GH-928).
+#
+# Based on the Open Quantum Safe OpenSSH fork (branch OQS-v10, OpenSSH 10.3p1).
+# Everything is compiled in the BUILD stage. The final image only has the
+# runtime files, so tests pull a small prebuilt image and need no compiler.
+#
+# Build:   docker buildx build --platform linux/amd64,linux/arm64 -t <name> .
+# Run:     docker run --rm -p 2222:22 <name>
+
+# Alpine 3.22.6 multi-arch index (includes linux/amd64 and linux/arm64).
+# The digest wins over the tag; update the digest to change the base image.
+FROM alpine:3.22.6@sha256:5291449c3df73caf6ed85e649dec1b9e818b39a5d8c871e97afc13e9cd5e8fa8 AS build
+# Pinned versions. Change them together and re-run the interop tests.
+# LIBOQS_REF is the commit of the 0.16.0 tag.
+ARG LIBOQS_REF=5a1a854b0dc9f2141bdc771c555ee60c37950183
+ARG OQS_OPENSSH_REF=10d74f8b27da43705cfab85923ac7e1d769416f1
+RUN apk add --no-cache build-base cmake ninja git autoconf automake \
+        openssl-dev zlib-dev linux-headers
+WORKDIR /src
+
+# liboqs. Do NOT use OQS_MINIMAL_BUILD: ssh-oqs.c references many signature
+# algorithms (mayo, ...), so the fork does not compile against a trimmed liboqs.
+RUN git init liboqs \
+ && git -C liboqs fetch --depth 1 https://github.com/open-quantum-safe/liboqs.git "${LIBOQS_REF}" \
+ && git -C liboqs checkout FETCH_HEAD \
+ && cmake -S liboqs -B liboqs/build -GNinja \
+        -DCMAKE_BUILD_TYPE=Release \
+        -DBUILD_SHARED_LIBS=ON \
+        -DCMAKE_INSTALL_PREFIX=/opt/oqs \
+        -DOQS_BUILD_ONLY_LIB=ON \
+        -DOQS_DIST_BUILD=ON \
+        -DOQS_USE_OPENSSL=ON \
+ && cmake --build liboqs/build \
+ && cmake --install liboqs/build
+
+# OQS-OpenSSH, installed under /opt/ssh.
+# The fork calls sshkey_clear_pkey() without a visible prototype (an upstream
+# header quirk). Its own CI hides this with -Wno-implicit-function-declaration;
+# GCC 14 (Alpine 3.22) needs the "-Wno-error=" form.
+RUN git clone https://github.com/open-quantum-safe/openssh.git openssh \
+ && git -C openssh checkout "${OQS_OPENSSH_REF}" \

Review Comment:
   fixed



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@mina.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@mina.apache.org
For additional commands, e-mail: dev-help@mina.apache.org