Skip to content

Commit 66c0e6d

Browse files
committed
test(agent): tolerate explicit-EC-param keys in pubkey derive
LibreSSL ssh-keygen emits "-m PEM" ECDSA keys with explicit curve params that mbedTLS cannot parse; skip those and add an OpenSSH-format case. Signed-off-by: Huang Rui <vowstar@gmail.com>
1 parent be57a8a commit 66c0e6d

1 file changed

Lines changed: 58 additions & 0 deletions

File tree

test/test_qsocsshpubderive.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,33 @@ class Test : public QObject
8888
return !QStandardPaths::findExecutable(QStringLiteral("ssh-keygen")).isEmpty();
8989
}
9090

91+
/* A named-curve P-256 key embeds the prime256v1 OID; an explicit-parameter
92+
* key (LibreSSL's "-m PEM" output) spells out the field prime instead and
93+
* lacks the OID. mbedTLS cannot parse the explicit form. */
94+
static bool keyHasExplicitEcParams(const QString &privPath)
95+
{
96+
QFile file(privPath);
97+
if (!file.open(QIODevice::ReadOnly)) {
98+
return false;
99+
}
100+
QByteArray body;
101+
bool inKey = false;
102+
const QList<QByteArray> lines = file.readAll().split('\n');
103+
for (const QByteArray &line : lines) {
104+
const QByteArray trimmed = line.trimmed();
105+
if (trimmed.startsWith("-----BEGIN EC PRIVATE KEY")) {
106+
inKey = true;
107+
} else if (trimmed.startsWith("-----END EC PRIVATE KEY")) {
108+
break;
109+
} else if (inKey) {
110+
body += trimmed;
111+
}
112+
}
113+
const QByteArray der = QByteArray::fromBase64(body);
114+
static const QByteArray kP256Oid = QByteArray::fromHex("06082a8648ce3d030107");
115+
return !der.isEmpty() && !der.contains(kP256Oid);
116+
}
117+
91118
private slots:
92119
void initTestCase() { TestApp::instance(); }
93120

@@ -136,6 +163,37 @@ private slots:
136163
QVERIFY(!want.isEmpty());
137164
QVERIFY(QFile::remove(priv + QStringLiteral(".pub")));
138165
const QString got = stripComment(QSocSshPubDerive::fromPrivateKeyFile(priv));
166+
if (got.isEmpty() && keyHasExplicitEcParams(priv)) {
167+
/* LibreSSL's ssh-keygen (macOS) writes "-m PEM" ECDSA keys with
168+
* explicit curve parameters, which mbedTLS cannot parse. Named
169+
* curves and the OpenSSH container are both supported and
170+
* exercised by the other cases. */
171+
QSKIP(
172+
"ssh-keygen emitted explicit EC parameters; mbedTLS cannot "
173+
"parse them. OpenSSH-format ECDSA is covered separately.");
174+
}
175+
QCOMPARE(got, want);
176+
}
177+
178+
void ecdsaP256OpensshContainer()
179+
{
180+
if (!haveSshKeygen()) {
181+
QSKIP("ssh-keygen not available, skipping.");
182+
}
183+
QTemporaryDir tmp;
184+
QVERIFY(tmp.isValid());
185+
QVERIFY(generateKey(
186+
tmp.path(),
187+
QStringLiteral("priv"),
188+
{QStringLiteral("-t"),
189+
QStringLiteral("ecdsa"),
190+
QStringLiteral("-b"),
191+
QStringLiteral("256")}));
192+
const QString priv = QDir(tmp.path()).absoluteFilePath(QStringLiteral("priv"));
193+
const QString want = readPubTruth(priv);
194+
QVERIFY(!want.isEmpty());
195+
QVERIFY(QFile::remove(priv + QStringLiteral(".pub")));
196+
const QString got = stripComment(QSocSshPubDerive::fromPrivateKeyFile(priv));
139197
QCOMPARE(got, want);
140198
}
141199

0 commit comments

Comments
 (0)