Skip to content

Commit 1f80a51

Browse files
committed
WIP: swtpm_cert: Enable CAs with ML-DSA key to sign a certifcate
Test for GNUTLS_PK_MLDSA44 to detect whether GnuTLS supports ML-DSA. Only SHAKE-256 can be used for hashing when ML-DSA is used for signing: https://github.com/gnutls/gnutls/blob/df24a53136f188d77aaffe66316b0fb6ba720d40/lib/algorithms/sign.c#L405-L428 The problem is now that the size of NVRAM indices is limited to MAX_NV_INDEX_SIZE = 2048, which is too small for a certificate created even with ML-DSA-44, which is around 2757 bytes long. Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
1 parent 0145dc1 commit 1f80a51

2 files changed

Lines changed: 45 additions & 4 deletions

File tree

configure.ac

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,25 @@ AS_IF([test "x$with_gnutls" != "xno"],
220220
[with_gnutls=no]
221221
)
222222
AS_IF([test "x$with_gnutls" != "xno"],[with_gnutls="yes"])
223+
AS_IF([test "x$with_gnutls" = "xyes"],
224+
[AC_COMPILE_IFELSE(
225+
[AC_LANG_PROGRAM(
226+
[[
227+
#include <gnutls/gnutls.h>
228+
#include <stdio.h>
229+
]],
230+
[[
231+
printf("%d", GNUTLS_PK_MLDSA44);
232+
]]
233+
)],
234+
[
235+
AC_MSG_RESULT("GnuTLS has ML-DSA support")
236+
AC_DEFINE_UNQUOTED([GNUTLS_SUPPORTS_MLDSA], 1,
237+
[whether GnuTLS support ML-DSA signing algorithm])
238+
],
239+
[AC_MSG_RESULT("GnuTLS has no ML-DSA support")],
240+
)]
241+
)
223242
]
224243
)
225244

src/swtpm_cert/ek-cert.c

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
* in section 3.5
4242
*/
4343

44+
#include "config.h"
45+
4446
#include <stdlib.h>
4547
#include <stdio.h>
4648
#include <string.h>
@@ -984,6 +986,27 @@ static char *get_password(const char *password)
984986
return result;
985987
}
986988

989+
/*
990+
* Get the hash algorithm for signing. TPM 1.2 used SHA1 and TPM 2 SHA256.
991+
* For an ML-DSA signing key only shake-256 is allowed.
992+
*/
993+
static int get_signing_hashalgo(int flags, gnutls_x509_privkey_t sigkey)
994+
{
995+
int keyalgo;
996+
997+
if (flags & CERT_TYPE_TPM2_F) {
998+
#ifdef GNUTLS_SUPPORTS_MLDSA
999+
keyalgo = gnutls_x509_privkey_get_pk_algorithm2(sigkey, NULL);
1000+
if (keyalgo == GNUTLS_PK_MLDSA44 ||
1001+
keyalgo == GNUTLS_PK_MLDSA65 ||
1002+
keyalgo == GNUTLS_PK_MLDSA87)
1003+
return GNUTLS_DIG_SHAKE_256;
1004+
#endif
1005+
return GNUTLS_DIG_SHA256;
1006+
}
1007+
return GNUTLS_DIG_SHA1;
1008+
}
1009+
9871010
static void capabilities_print_json(void)
9881011
{
9891012
fprintf(stdout,
@@ -1018,7 +1041,7 @@ main(int argc, char *argv[])
10181041
int ecc_y_len = 0;
10191042
const char *ecc_curveid = NULL;
10201043
gnutls_datum_t datum = { NULL, 0}, out = { NULL, 0};
1021-
gnutls_digest_algorithm_t hashAlgo = GNUTLS_DIG_SHA1;
1044+
gnutls_digest_algorithm_t hashAlgo;
10221045
mpz_t serial;
10231046
time_t now;
10241047
int err;
@@ -1261,9 +1284,6 @@ main(int argc, char *argv[])
12611284
}
12621285
}
12631286

1264-
if (flags & CERT_TYPE_TPM2_F)
1265-
hashAlgo = GNUTLS_DIG_SHA256;
1266-
12671287
if ((mpz_sizeinbase(serial, 2) + 7) / 8 > sizeof(ser_number) - 1) {
12681288
fprintf(stderr, "Serial number is too large.\n");
12691289
goto cleanup;
@@ -1704,6 +1724,8 @@ if (_err != GNUTLS_E_SUCCESS) { \
17041724
CHECK_GNUTLS_ERROR(err, "Could not set public EK on CRT: %s\n",
17051725
gnutls_strerror(err))
17061726

1727+
hashAlgo = get_signing_hashalgo(flags, sigkey);
1728+
17071729
/* sign cert */
17081730
if (sigkey) {
17091731
err = gnutls_x509_crt_sign2(crt, sigcert, sigkey, hashAlgo, 0);

0 commit comments

Comments
 (0)