Skip to content

Commit e4714a4

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 11e1674 commit e4714a4

2 files changed

Lines changed: 46 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: 27 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,28 @@ 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+
if (flags & CERT_TYPE_TPM2_F) {
996+
int keyalgo = gnutls_x509_privkey_get_pk_algorithm2(sigkey, NULL);
997+
switch (keyalgo) {
998+
#ifdef GNUTLS_SUPPORTS_MLDSA
999+
case GNUTLS_PK_MLDSA44:
1000+
case GNUTLS_PK_MLDSA65:
1001+
case GNUTLS_PK_MLDSA87:
1002+
return GNUTLS_DIG_SHAKE_256;
1003+
#endif
1004+
default:
1005+
return GNUTLS_DIG_SHA256;
1006+
}
1007+
}
1008+
return GNUTLS_DIG_SHA1;
1009+
}
1010+
9871011
static void capabilities_print_json(void)
9881012
{
9891013
fprintf(stdout,
@@ -1018,7 +1042,7 @@ main(int argc, char *argv[])
10181042
int ecc_y_len = 0;
10191043
const char *ecc_curveid = NULL;
10201044
gnutls_datum_t datum = { NULL, 0}, out = { NULL, 0};
1021-
gnutls_digest_algorithm_t hashAlgo = GNUTLS_DIG_SHA1;
1045+
gnutls_digest_algorithm_t hashAlgo;
10221046
mpz_t serial;
10231047
time_t now;
10241048
int err;
@@ -1261,9 +1285,6 @@ main(int argc, char *argv[])
12611285
}
12621286
}
12631287

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

1728+
hashAlgo = get_signing_hashalgo(flags, sigkey);
1729+
17071730
/* sign cert */
17081731
if (sigkey) {
17091732
err = gnutls_x509_crt_sign2(crt, sigcert, sigkey, hashAlgo, 0);

0 commit comments

Comments
 (0)