diff --git a/.gitignore b/.gitignore index cb632f7..1777de8 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,11 @@ create-container hashkeys Makefile print-container +gendilkey +gendilsig +verifydilsig +extractdilkey bin/ +*.o +*.a + diff --git a/Makefile.am b/Makefile.am index 58e99e8..c141287 100644 --- a/Makefile.am +++ b/Makefile.am @@ -26,6 +26,9 @@ ACLOCAL_AMFLAGS = -I m4 bin_PROGRAMS = create-container print-container hashkeys +if ADD_DILITHIUM +bin_PROGRAMS += gendilkey gendilsig verifydilsig extractdilkey +endif dist_bin_SCRIPTS = bulkSign.sh crtSignedContainer.sh sign-with-local-keys.sh @@ -42,9 +45,10 @@ create_container_LDADD = -lssl -lcrypto print_container_SOURCES = \ print-container.c -print_container_CPPFLAGS = $(AM_CPPFLAGS) -I. -g3 -std=gnu99 +print_container_CPPFLAGS = $(AM_CPPFLAGS) -I. -g3 -std=gnu99 ${DIL_CPPFLAGS} + print_container_LDFLAGS = -print_container_LDADD = -lssl -lcrypto +print_container_LDADD = -lssl -lcrypto ${DIL_LDADD} hashkeys_SOURCES = \ hashkeys.c @@ -52,3 +56,26 @@ hashkeys_SOURCES = \ hashkeys_CPPFLAGS = $(AM_CPPFLAGS) -I. -g3 -std=gnu99 hashkeys_LDFLAGS = hashkeys_LDADD = -lssl -lcrypto + + +if ADD_DILITHIUM +gendilkey_SOURCES = gendilkey.c +gendilkey_CPPFLAGS = $(AM_CPPFLAGS) -I. ${DIL_CPPFLAGS} -g3 -std=gnu99 +gendilkey_LDFLAGS = +gendilkey_LDADD = ${DIL_LDADD} + +gendilsig_SOURCES = gendilsig.c +gendilsig_CPPFLAGS = $(AM_CPPFLAGS) -I. ${DIL_CPPFLAGS} -g3 -std=gnu99 +gendilsig_LDFLAGS = +gendilsig_LDADD = ${DIL_LDADD} + +verifydilsig_SOURCES = verifydilsig.c +verifydilsig_CPPFLAGS = $(AM_CPPFLAGS) -I. ${DIL_CPPFLAGS} -g3 -std=gnu99 +verifydilsig_LDFLAGS = +verifydilsig_LDADD = ${DIL_LDADD} + +extractdilkey_SOURCES = extractdilkey.c +extractdilkey_CPPFLAGS = $(AM_CPPFLAGS) -I. ${DIL_CPPFLAGS} -g3 -std=gnu99 +extractdilkey_LDFLAGS = +extractdilkey_LDADD = ${DIL_LDADD} +endif diff --git a/Makefile.lite b/Makefile.lite index b52b51c..7b94695 100644 --- a/Makefile.lite +++ b/Makefile.lite @@ -10,7 +10,7 @@ hashkeys: hashkeys.c $(CC) -g -Wall -Wextra -I. $^ -o $@ -lssl -lcrypto -std=gnu99 clean: - $(RM) create-container print-container hashkeys + $(RM) create-container print-container hashkeys *.o prefix = /usr/local exec_prefix = $(prefix) diff --git a/Makefile.v2 b/Makefile.v2 new file mode 100644 index 0000000..c2dafb7 --- /dev/null +++ b/Makefile.v2 @@ -0,0 +1,38 @@ +all: create-container print-container hashkeys gendilkey gendilsig verifydilsig extractdilkey + +create-container: create-container.c + $(CC) -g -Wall -Wextra -I. $^ -o $@ -lssl -lcrypto -std=gnu99 + +print-container: print-container.c + $(CC) -g -Wall -Wextra -I. $^ -o $@ -lssl -lcrypto -std=gnu99 -DADD_DILITHIUM -I${MLCA_PATH}/include -I${MLCA_PATH}/qsc/crystals ${MLCA_PATH}/build/libmlca2.a + +hashkeys: hashkeys.c + $(CC) -g -Wall -Wextra -I. $^ -o $@ -lssl -lcrypto -std=gnu99 + +gendilkey: gendilkey.c + $(CC) -g -Wall -Wextra -I. -I${MLCA_PATH}/include -I${MLCA_PATH}/qsc/crystals $^ -o $@ ${MLCA_PATH}/build/libmlca2.a -std=gnu99 + +gendilsig: gendilsig.c + $(CC) -g -Wall -Wextra -I. -I${MLCA_PATH}/include -I${MLCA_PATH}/qsc/crystals $^ -o $@ ${MLCA_PATH}/build/libmlca2.a -std=gnu99 + +verifydilsig: verifydilsig.c + $(CC) -g -Wall -Wextra -I. -I${MLCA_PATH}/include -I${MLCA_PATH}/qsc/crystals $^ -o $@ ${MLCA_PATH}/build/libmlca2.a -std=gnu99 + +extractdilkey: extractdilkey.c + $(CC) -g -Wall -Wextra -I. -I${MLCA_PATH}/include -I${MLCA_PATH}/qsc/crystals $^ -o $@ ${MLCA_PATH}/build/libmlca2.a -std=gnu99 + +clean: + $(RM) create-container print-container hashkeys gendilkey gendilsig verifydilsig extractdilkey + +prefix = /usr/local +exec_prefix = $(prefix) +bindir = $(exec_prefix)/bin + +install: + cp create-container print-container hashkeys gendilkey gendilsig verifydilsig extractdilkey "$(bindir)" + cp bulkSign.sh crtSignedContainer.sh sign-with-local-keys.sh "$(bindir)" + +uninstall: + cd "$(bindir)" && $(RM) create-container print-container hashkeys gendilkey gendilsig verifydilsig extractdilkey + cd "$(bindir)" && $(RM) bulkSign.sh crtSignedContainer.sh sign-with-local-keys.sh + diff --git a/build_all.sh b/build_all.sh index 1a2e1a6..cc9d6b0 100755 --- a/build_all.sh +++ b/build_all.sh @@ -9,6 +9,15 @@ case "$(echo "$1" | tr "[:upper:]" "[:lower:]")" in cp -p Makefile.lite Makefile make ;; + v2) + if [ "X$MLCA_PATH" = "X" ]; then + echo "Must set MLCA_PATH env variable to point to mlca_framework repository" + exit 1 + fi + cp -p config.h.lite config.h + cp -p Makefile.v2 Makefile + make + ;; gnu) autoreconf -i -Wno-unsupported && \ ./configure && \ @@ -19,6 +28,15 @@ case "$(echo "$1" | tr "[:upper:]" "[:lower:]")" in cp -p Makefile.aix Makefile gnu-make ;; + gnuv2) + if [ "X$MLCA_PATH" = "X" ]; then + echo "Must set MLCA_PATH env variable to point to mlca_framework repository" + exit 1 + fi + autoreconf -i -Wno-unsupported && \ + ./configure --enable-sign-v2 && \ + make + ;; *) echo "Unknown build type: $1" exit 1 diff --git a/configure.ac b/configure.ac index 2547b9e..887f50f 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ # autoconf script AC_PREREQ([2.65]) -AC_INIT(sb-signtool, 0.9, matthew.vaught@ibm.com) +AC_INIT(sb-signtool, 0.10, matthew.vaught@ibm.com) AM_INIT_AUTOMAKE([foreign]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_MACRO_DIR([m4]) @@ -58,6 +58,28 @@ AC_CHECK_HEADERS(openssl/sha.h) AM_CPPFLAGS="-Wall -Wextra" AC_SUBST(AM_CPPFLAGS) +# Add optional v2/dilithium support +AC_ARG_VAR(MLCA_PATH, [Path to MLCA repository]) + +DIL_CPPFLAGS= +DIL_LDADD= +AC_ARG_ENABLE([sign-v2], + AS_HELP_STRING([--enable-sign-v2], [Enable support for v2 containers]) ) +AM_CONDITIONAL([ADD_DILITHIUM], [test "x$enable_sign_v2" = "xyes"]) +AS_IF([test "x$enable_sign_v2" = "xyes"], [ + PKG_CHECK_MODULES(OPENSSL, [ openssl >= 1.1 ]) + DIL_CPPFLAGS="-DADD_DILITHIUM" + DIL_LDADD="-lmlca2_shared" + AS_IF([test "x$MLCA_PATH" != "x"], [ + DIL_CPPFLAGS+=" -I${MLCA_PATH}/include -I${MLCA_PATH}/qsc/crystals" + DIL_LDADD="${MLCA_PATH}/build/libmlca2.a" + ]) + +]) +AC_SUBST(DIL_CPPFLAGS) +AC_SUBST(DIL_LDADD) +# AC_CHECK_LIB for mlca library + AC_CONFIG_FILES([Makefile]) AC_OUTPUT diff --git a/extractdilkey.c b/extractdilkey.c new file mode 100644 index 0000000..9aa8324 --- /dev/null +++ b/extractdilkey.c @@ -0,0 +1,304 @@ +/* Copyright 2024 IBM Corp. + * + * Licensed 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. + */ + +#include "crystals-oids.h" +#include "dilutils.h" +#include "mlca2.h" +#include "pqalgs.h" + +#include +#include +#include +#include + +#define BUF_SIZE 8000 + +int main(int argc, char** argv) +{ + size_t sRawBytes = BUF_SIZE; + size_t sKeyBytes = BUF_SIZE; + int sRc = 0; + int sIdx = 0; + int sMlcaRet = 0; + bool sPubIn = false; + bool sPubOut = false; + bool sRawIn = false; + bool sRawOut = false; + const char* sInFile = NULL; + const char* sOutFile = NULL; + bool sPrintHelp = false; + bool sVerbose = false; + + for(sIdx = 1; sIdx < argc; sIdx++) + { + if(strcmp(argv[sIdx], "-h") == 0) + { + sPrintHelp = true; + } + else if(strcmp(argv[sIdx], "-k") == 0) + { + sIdx++; + sInFile = argv[sIdx]; + } + else if(strcmp(argv[sIdx], "-o") == 0) + { + sIdx++; + sOutFile = argv[sIdx]; + } + else if(strcmp(argv[sIdx], "-pubin") == 0) + { + sPubIn = true; + } + else if(strcmp(argv[sIdx], "-pubout") == 0) + { + sPubOut = true; + } + else if(strcmp(argv[sIdx], "-outraw") == 0) + { + sRawOut = true; + } + else if(strcmp(argv[sIdx], "-inraw") == 0) + { + sRawIn = true; + } + else if(strcmp(argv[sIdx], "-v") == 0) + { + sVerbose = true; + } + else + { + printf("**** ERROR : Unknown parameter : %s\n", argv[sIdx]); + sPrintHelp = true; + } + } + + if(!sPrintHelp && (NULL == sInFile || (NULL == sOutFile && sRawOut))) + { + printf("**** ERROR : Invalid input parms\n"); + sPrintHelp = true; + } + + if(sPrintHelp) + { + printf( + "\nextractdilkey -k [-pubin] [-inraw] [-o [-outraw]]\n"); + exit(0); + } + + unsigned char* sRawKey = malloc(BUF_SIZE); + unsigned char* sKey = malloc(BUF_SIZE); + + if(!sRawKey || !sKey) + { + printf("**** ERROR : Allocation Failure\n"); + exit(1); + } + + sRc = readFile(sKey, &sKeyBytes, sInFile); + if(0 != sRc) + { + printf("**** ERROR : Unable to read from : %s\n", sInFile); + sRc = 1; + } + if(sVerbose) + { + printf("extractdilkey: Key Size: %d\n", (int)sKeyBytes); + } + do + { + // Now validate our input + if(0 == sRc && sPubIn) + { + if(sRawIn) + { + // We have a raw Dilithium R2 8x7 public key + if(RawDilithiumR28x7PublicKeySize == sKeyBytes) + { + // We have a raw public key, lets convert it + if(sVerbose) + printf("extractdilkey: Found raw public key\n"); + memcpy(sRawKey, sKey, sKeyBytes); + sRawBytes = sKeyBytes; + + sKeyBytes = BUF_SIZE; + + // Convert public key + sMlcaRet = mlca_key2wire( + sKey, sKeyBytes, sRawKey, sRawBytes, 0, NULL, 0, NULL, 0); + if(sMlcaRet < 0) + { + printf("**** ERROR: Failure during public key conversion : %d\n", sMlcaRet); + sRc = 1; + break; + } + sKeyBytes = sMlcaRet; + } + else + { + printf("**** ERROR: Unrecognized raw public key : %s\n", sInFile); + sRc = 1; + break; + } + } + else + { + // Attempt to convert encoded key + unsigned int sWireType = 0; + sMlcaRet = mlca_wire2key(sRawKey, sRawBytes, &sWireType, sKey, sKeyBytes, NULL, ~0); + if(sVerbose) + printf("extractdilkey: Found public key\n"); + // We have a raw Dilithium R2 8x7 public key + if(RawDilithiumR28x7PublicKeySize != sMlcaRet) + { + printf("**** ERROR: Unable to convert public key : %d\n", sMlcaRet); + sRc = 1; + break; + } + else + { + sRawBytes = sMlcaRet; + } + } + + if(NULL != sOutFile) + { + printf("Writing public key to : %s\n", sOutFile); + if(sRawOut) + { + sRc = writeFile(sRawKey, sRawBytes, sOutFile); + } + else + { + sRc = writeFile(sKey, sKeyBytes, sOutFile); + } + } + else + { + printf("Valid Dilithium public keyfile detected\n"); + } + } + + // Private keys + else if(0 == sRc && !sPubIn) + { + if(sRawIn) + { + // Raw private key size for dilithium r2 8/7 + if(RawDilithiumR28x7PrivateKeySize == sKeyBytes) + { + if(sVerbose) + printf("extractdilkey: Found raw private key\n"); + // We have a raw private key, lets convert it + memcpy(sRawKey, sKey, sKeyBytes); + sRawBytes = sKeyBytes; + + sKeyBytes = BUF_SIZE; + + // TODO , convert raw private key to encoded format without the public key + if(sOutFile) + { + sRc = 1; + printf("**** ERROR: Unable to convert private raw -> encoded\n"); + break; + } + } + else + { + printf("**** ERROR: Unrecognized raw private key : %s\n", sInFile); + sRc = 1; + break; + } + } + else + { + // Attempt to convert encoded key + unsigned int sWireType = 0; + if(sPubOut) + { + // Get the raw public key + sMlcaRet = mlca_wire2key(sRawKey, + sRawBytes, + &sWireType, + sKey, + sKeyBytes, + (const unsigned char*)CR_OID_SPECIAL_PRV2PUB, + CR_OID_SPECIAL_PRV2PUB_BYTES); + if(0 >= sMlcaRet) + { + printf("**** ERROR: Unable to convert private key : %d\n", sMlcaRet); + sRc = 1; + break; + } + else + { + sRawBytes = sMlcaRet; + } + if(sVerbose) + printf("extractdilkey: Found public key\n"); + + // Encode it + sMlcaRet = mlca_key2wire( + sKey, sKeyBytes, sRawKey, sRawBytes, 0, NULL, 0, NULL, 0); + if(sMlcaRet < 0) + { + printf("**** ERROR: Failure during public key conversion : %d\n", sMlcaRet); + sRc = 1; + break; + } + sKeyBytes = sMlcaRet; + } + else + { + sMlcaRet = mlca_wire2key( + sRawKey, sRawBytes, &sWireType, sKey, sKeyBytes, NULL, ~0); + + // Raw private key size for dilithium r2 8/7 + if(0 >= sMlcaRet || RawDilithiumR28x7PrivateKeySize != sMlcaRet) + { + printf("**** ERROR: Unable to convert private key : %d\n", sMlcaRet); + sRc = 1; + break; + } + else + { + sRawBytes = sMlcaRet; + } + } + } + + if(NULL != sOutFile) + { + printf("Writing private key to : %s\n", sOutFile); + if(sRawOut) + { + sRc = writeFile(sRawKey, sRawBytes, sOutFile); + } + else + { + sRc = writeFile(sKey, sKeyBytes, sOutFile); + } + } + else + { + printf("Valid Dilithium private keyfile detected\n"); + } + } + } while(0); + + free(sKey); + free(sRawKey); + exit(sRc); +} diff --git a/gendilkey.c b/gendilkey.c new file mode 100644 index 0000000..38b889f --- /dev/null +++ b/gendilkey.c @@ -0,0 +1,189 @@ +/* Copyright 2024 IBM Corp. + * + * Licensed 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. + */ + +#include "dilutils.h" +#include "mlca2.h" +#include "pqalgs.h" + +#include +#include +#include +#include + +#define BUF_SIZE 8000 + +int main(int argc, char** argv) +{ + size_t sPrivKeyBytes = BUF_SIZE; + size_t sPubKeyBytes = BUF_SIZE; + size_t sWirePrivKeyBytes = BUF_SIZE; + size_t sWirePubKeyBytes = BUF_SIZE; + int sIdx = 0; + int sRc = 0; + bool sPrintHelp = false; + const char* sPubKeyFile = NULL; + const char* sPrivKeyFile = NULL; + + for(sIdx = 1; sIdx < argc; sIdx++) + { + if(strcmp(argv[sIdx], "-h") == 0) + { + sPrintHelp = true; + } + else if(strcmp(argv[sIdx], "-pub") == 0) + { + sIdx++; + sPubKeyFile = argv[sIdx]; + } + else if(strcmp(argv[sIdx], "-priv") == 0) + { + sIdx++; + sPrivKeyFile = argv[sIdx]; + } + else + { + printf("**** ERROR : Unknown parameter : %s\n", argv[sIdx]); + sPrintHelp = true; + } + } + + if(!sPrintHelp && (NULL == sPubKeyFile || NULL == sPrivKeyFile)) + { + printf("**** ERROR : Missing input parms\n"); + sPrintHelp = true; + } + + if(sPrintHelp) + { + printf("\ngendilkey -priv -pub \n"); + exit(0); + } + + mlca_ctx_t sCtx; + MLCA_RC sMlRc = 0; + unsigned char* sPubKey = malloc(BUF_SIZE); + unsigned char* sPrivKey = malloc(BUF_SIZE); + unsigned char* sWirePubKey = malloc(BUF_SIZE); + unsigned char* sWirePrivKey = malloc(BUF_SIZE); + + if(!sPubKey || !sPrivKey || !sWirePubKey || !sWirePrivKey) + { + printf("**** ERROR : Allocation Failure\n"); + exit(1); + } + + if(0 == sRc) + { + sMlRc = mlca_init(&sCtx, 1, 0); + if(sMlRc) + { + printf("**** ERROR : Failed mlca_init : %d\n", sMlRc); + sRc = 1; + } + } + if(0 == sRc) + { + sMlRc = mlca_set_alg(&sCtx, MLCA_ALGORITHM_SIG_DILITHIUM_R2_8x7_OID, OPT_LEVEL_AUTO); + if(sMlRc) + { + printf("**** ERROR : Failed mlca_set_alg : %d\n", sMlRc); + sRc = 1; + } + } + if(0 == sRc) + { + sMlRc = mlca_set_encoding_by_idx(&sCtx, 0); + if(sMlRc) + { + printf("**** ERROR : Failed mlca_set_encoding_by_name_oid : %d\n", sMlRc); + sRc = 1; + } + } + + if(0 == sRc) + { + printf("Generating Dilthium R2 8x7 key pair ...\n"); + sPubKeyBytes = mlca_sig_crypto_publickeybytes(&sCtx); + sPrivKeyBytes = mlca_sig_crypto_secretkeybytes(&sCtx); + sMlRc = mlca_sig_keygen(&sCtx, sPubKey, sPrivKey); + if(sMlRc) + { + printf("**** ERROR : Failed mlca_sig_keygen : %d\n", sMlRc); + sRc = 1; + } + } + + if(0 == sRc) + { + // Convert private key + sRc = mlca_key2wire(sWirePrivKey, + sWirePrivKeyBytes, + sPrivKey, + sPrivKeyBytes, + 0, + sPubKey, + sPubKeyBytes, + NULL, + ~0); + if(sRc < 0) + { + printf("**** ERROR: Failure during private key conversion : %d\n", sRc); + } + else + { + sWirePrivKeyBytes = sRc; + sRc = 0; + } + } + + if(0 == sRc) + { + + // Convert public key + sRc = mlca_key2wire( + sWirePubKey, sWirePubKeyBytes, sPubKey, sPubKeyBytes, 0, NULL, 0, NULL, 0); + if(sRc < 0) + { + printf("**** ERROR: Failure during public key conversion : %d\n", sRc); + sRc = 1; + } + else + { + sWirePubKeyBytes = sRc; + sRc = 0; + } + } + + if(0 == sRc) + { + writeFile(sWirePrivKey, sWirePrivKeyBytes, sPrivKeyFile); + writeFile(sWirePubKey, sWirePubKeyBytes, sPubKeyFile); + + printf("Private Key Size : %lu\n", sPrivKeyBytes); + printf("Public Key Size : %lu\n", sPubKeyBytes); + + printf("Private Key File : %s\n", sPrivKeyFile); + printf("Public Key File : %s\n", sPubKeyFile); + } + + free(sPrivKey); + free(sPubKey); + free(sWirePrivKey); + free(sWirePubKey); + + mlca_ctx_free(&sCtx); + exit(sRc); +} diff --git a/gendilsig.c b/gendilsig.c new file mode 100644 index 0000000..188461f --- /dev/null +++ b/gendilsig.c @@ -0,0 +1,210 @@ +/* Copyright 2024 IBM Corp. + * + * Licensed 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. + */ + +#include "crystals-oids.h" +#include "dilutils.h" +#include "mlca2.h" +#include "pqalgs.h" + +#include +#include +#include +#include + +#define BUF_SIZE 8000 + +int main(int argc, char** argv) +{ + size_t sPrivKeyBytes = BUF_SIZE; + size_t sWirePrivKeyBytes = BUF_SIZE; + size_t sDigestBytes = BUF_SIZE; + size_t sSignatureBytes = BUF_SIZE; + int sRc = 0; + int sIdx = 0; + const char* sPrivKeyFile = NULL; + const char* sDigestFile = NULL; + const char* sSigFile = NULL; + bool sPrintHelp = false; + bool sVerbose = false; + + for(sIdx = 1; sIdx < argc; sIdx++) + { + if(strcmp(argv[sIdx], "-h") == 0) + { + sPrintHelp = true; + } + else if(strcmp(argv[sIdx], "-i") == 0) + { + sIdx++; + sDigestFile = argv[sIdx]; + } + else if(strcmp(argv[sIdx], "-k") == 0) + { + sIdx++; + sPrivKeyFile = argv[sIdx]; + } + else if(strcmp(argv[sIdx], "-o") == 0) + { + sIdx++; + sSigFile = argv[sIdx]; + } + else if(strcmp(argv[sIdx], "-v") == 0) + { + sVerbose = true; + } + else + { + printf("**** ERROR : Unknown parameter : %s\n", argv[sIdx]); + sPrintHelp = true; + } + } + + if(!sPrintHelp && (NULL == sDigestFile || NULL == sPrivKeyFile || NULL == sSigFile)) + { + printf("**** ERROR : Missing input parms\n"); + sPrintHelp = true; + } + + if(sPrintHelp) + { + printf("\ngendilsig -i -k -o \n"); + exit(0); + } + + mlca_ctx_t sCtx; + MLCA_RC sMlRc = 0; + unsigned char* sDigest = malloc(BUF_SIZE); + unsigned char* sSignature = malloc(BUF_SIZE); + unsigned char* sPrivKey = malloc(BUF_SIZE); + unsigned char* sWirePrivKey = malloc(BUF_SIZE); + + if(!sDigest || !sSignature || !sPrivKey || !sWirePrivKey) + { + printf("**** ERROR : Allocation Failure\n"); + exit(1); + } + + sRc = readFile(sDigest, &sDigestBytes, sDigestFile); + if(0 == sRc && SHA3_512_DigestSize != sDigestBytes) + { + printf("**** ERROR : %s doesn't appear to be a SHA3-512 digest\n", sDigestFile); + sRc = 1; + } + + if(0 == sRc) + { + sRc = readFile(sWirePrivKey, &sWirePrivKeyBytes, sPrivKeyFile); + } + + // Convert the key + if(0 == sRc) + { + // Raw private key size for dilithium r2 8/7 + if(RawDilithiumR28x7PrivateKeySize == sWirePrivKeyBytes) + { + if(sVerbose) + printf("gendilsig: Found raw private key\n"); + + // Raw key, just copy + memcpy(sPrivKey, sWirePrivKey, sWirePrivKeyBytes); + sPrivKeyBytes = sWirePrivKeyBytes; + } + else + { + if(sVerbose) + printf("gendilsig: Found private key\n"); + + unsigned int sWireType = 0; + sRc = mlca_wire2key( + sPrivKey, sPrivKeyBytes, &sWireType, sWirePrivKey, sWirePrivKeyBytes, NULL, ~0); + if(0 >= sRc || RawDilithiumR28x7PrivateKeySize != sRc) + { + printf("**** ERROR: Unable to convert raw private key : %d\n", sRc); + sRc = 1; + } + else + { + sPrivKeyBytes = sRc; + sRc = 0; + } + } + } + + if(0 == sRc) + { + sMlRc = mlca_init(&sCtx, 1, 0); + if(sMlRc) + { + printf("**** ERROR : Failed mlca_init : %d\n", sMlRc); + sRc = 1; + } + } + if(0 == sRc) + { + sMlRc = mlca_set_alg(&sCtx, MLCA_ALGORITHM_SIG_DILITHIUM_R2_8x7_OID, OPT_LEVEL_AUTO); + if(sMlRc) + { + printf("**** ERROR : Failed mlca_set_alg : %d\n", sMlRc); + sRc = 1; + } + } + if(0 == sRc) + { + sMlRc = mlca_set_encoding_by_idx(&sCtx, 0); + if(sMlRc) + { + printf("**** ERROR : Failed mlca_set_encoding_by_name_oid : %d\n", sMlRc); + sRc = 1; + } + } + + if(0 == sRc) + { + printf("Generating Dilthium R2 8x7 signature ...\n"); + int gRc = mlca_sign(sSignature, + sSignatureBytes, /// validate RC + sDigest, + sDigestBytes, + sPrivKey, + sPrivKeyBytes, + (const unsigned char*)CR_OID_DIL_R2_8x7, + CR_OID_DIL_R2_8x7_BYTES); + if(gRc < 0) + { + printf("**** ERROR: Failure during signature generation : %d\n", sMlRc); + sRc = 1; + } + else + { + sSignatureBytes = gRc; + } + } + + if(0 == sRc) + { + printf("Signature Size : %lu\n", sSignatureBytes); + + writeFile(sSignature, sSignatureBytes, sSigFile); + } + + free(sDigest); + free(sSignature); + free(sPrivKey); + free(sWirePrivKey); + mlca_ctx_free(&sCtx); + + exit(sRc); +} diff --git a/print-container.c b/print-container.c index 99e8ff6..e421c2e 100644 --- a/print-container.c +++ b/print-container.c @@ -48,8 +48,7 @@ #include "container.h" #ifdef ADD_DILITHIUM -#include "pqalgs.h" -#include "crystals-oids.h" +#include "mlca2.h" #endif char *progname; @@ -84,7 +83,8 @@ static bool verify_signature(const char *moniker, const unsigned char *dgst, static bool verify_dilithium_signature(const char *moniker, const unsigned char *dgst, int dgst_len, const dilithium_signature_t sig_raw, const dilithium_key_t key_raw); -unsigned char *sha3_512(const unsigned char *data, size_t len, unsigned char *md) + +unsigned char *ossl_sha3_512(const unsigned char *data, size_t len, unsigned char *md) { #if OPENSSL_VERSION_NUMBER >= 0x10100000L const EVP_MD* alg = EVP_sha3_512(); @@ -362,7 +362,7 @@ static void display_container_v2(struct parsed_stb_container_v2 c) print_bytes((char *) "hw_pkey_d: ", (uint8_t *) c.c->hw_pkey_d, sizeof(c.c->hw_pkey_d)); - p = sha3_512(c.c->hw_pkey_a, sizeof(ecc_key_t) + sizeof(dilithium_key_t), md); + p = ossl_sha3_512(c.c->hw_pkey_a, sizeof(ecc_key_t) + sizeof(dilithium_key_t), md); if (!p) die(EX_SOFTWARE, "%s", "Cannot get SHA3-512"); printf("HW keys hash (calculated):\n"); @@ -527,7 +527,7 @@ static bool validate_container_v2(struct parsed_stb_container_v2 c, int fdin) size_t sSwKeySize = 0; // Get Prefix header hash. - p = sha3_512((uint8_t *) c.ph, sizeof(ROM_prefix_header_v2_raw), md); + p = ossl_sha3_512((uint8_t *) c.ph, sizeof(ROM_prefix_header_v2_raw), md); if (!p) die(EX_SOFTWARE, "%s", "Cannot get SHA512"); if (verbose) print_bytes((char *) "PR header hash = ", (uint8_t *) md, @@ -549,7 +549,7 @@ static bool validate_container_v2(struct parsed_stb_container_v2 c, int fdin) if (verbose) printf("\n"); // Get SW header hash. - p = sha3_512((uint8_t *) c.sh, sizeof(ROM_sw_header_v2_raw), md); + p = ossl_sha3_512((uint8_t *) c.sh, sizeof(ROM_sw_header_v2_raw), md); if (!p) die(EX_SOFTWARE, "%s", "Cannot get SHA512"); if (verbose) print_bytes((char *) "SW header hash = ", (uint8_t *) md, @@ -590,7 +590,7 @@ static bool validate_container_v2(struct parsed_stb_container_v2 c, int fdin) if (verbose) printf("\n"); // Verify SW keys hash. - p = sha3_512(c.pd->sw_pkey_p, sSwKeySize, md); + p = ossl_sha3_512(c.pd->sw_pkey_p, sSwKeySize,md ); if (!p) die(EX_SOFTWARE, "%s", "Cannot get SHA512"); if (verbose) print_bytes((char *) "SW keys hash = ", (uint8_t *) md, @@ -644,7 +644,7 @@ static bool verify_container_v2(struct parsed_stb_container_v2 c, char * verify) void *md = alloca(SHA512_DIGEST_LENGTH); void *p; - p = sha3_512(c.c->hw_pkey_a, sizeof(ecc_key_t) + sizeof(dilithium_key_t), md); + p = ossl_sha3_512(c.c->hw_pkey_a, sizeof(ecc_key_t) + sizeof(dilithium_key_t), md); if (!p) die(EX_SOFTWARE, "%s", "Cannot get SHA512"); if (verbose) print_bytes((char *) "HW keys hash = ", (uint8_t *) md, @@ -753,20 +753,44 @@ static bool verify_dilithium_signature(const char *moniker, const unsigned char { bool sRet = false; #ifdef ADD_DILITHIUM + mlca_ctx_t sCtx; + MLCA_RC sMlRc = 0; - int vRc = pqca_verify(sig_raw, sizeof(dilithium_signature_t), - dgst, dgst_len, - key_raw, sizeof(dilithium_key_t), - (const unsigned char *)CR_OID_DIL_R2_8x7, - CR_OID_DIL_R2_8x7_BYTES); - if (vRc == 1) { - if (verbose) printf("%s signature is good: VERIFIED ./\n", moniker); - sRet = true; - } else if (vRc == 0) { - if (verbose) printf("%s signature FAILED to verify.\n", moniker); - sRet = false; - } else { - die(EX_SOFTWARE, "%s", "Cannot Dilithium_do_verify"); + sMlRc = mlca_init(&sCtx,1,0); + if (sMlRc) + { + printf("**** ERROR : Failed mlca_init : %d\n", sMlRc); + } + if (0 == sMlRc) + { + sMlRc = mlca_set_alg(&sCtx, MLCA_ALGORITHM_SIG_DILITHIUM_R2_8x7_OID, OPT_LEVEL_AUTO); + if (sMlRc) + { + printf("**** ERROR : Failed mlca_set_alg : %d\n", sMlRc); + } + } + if (0 == sMlRc) + { + sMlRc = mlca_set_encoding_by_idx(&sCtx, 0); + if (sMlRc) + { + printf("**** ERROR : Failed mlca_set_encoding_by_name_oid : %d\n", sMlRc); + } + } + if (0 == sMlRc) + { + printf("Verifying Dilthium R2 8x7 signature ...\n"); + sMlRc = mlca_sig_verify(&sCtx, dgst, dgst_len, sig_raw, sizeof(dilithium_signature_t), key_raw); + if (1 != sMlRc) + { + if (verbose) printf("%s signature FAILED to verify.\n", moniker); + sRet = false; + } + else + { + if (verbose) printf("%s signature is good: VERIFIED ./\n", moniker); + sRet = true; + } } #else die(EX_SOFTWARE, "%s", "Cannot Dilithium_do_verify"); @@ -810,7 +834,7 @@ static bool getPayloadHash(int fdin, uint64_t pl_sz_expected, unsigned char *md, (params.ignore_remainder ? min(pl_sz_actual, pl_sz_expected) : pl_sz_actual), md); } else { - p = sha3_512(file + SECURE_BOOT_HEADERS_V2_SIZE, + p = ossl_sha3_512(file + SECURE_BOOT_HEADERS_V2_SIZE, (params.ignore_remainder ? min(pl_sz_actual, pl_sz_expected) : pl_sz_actual), md); } diff --git a/verifydilsig.c b/verifydilsig.c new file mode 100644 index 0000000..7664ddb --- /dev/null +++ b/verifydilsig.c @@ -0,0 +1,184 @@ +/* Copyright 2024 IBM Corp. + * + * Licensed 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. + */ + +#include "dilutils.h" +#include "mlca2.h" +#include "pqalgs.h" + +#include +#include +#include +#include + +#define BUF_SIZE 8000 + +int main(int argc, char** argv) +{ + size_t sPubKeyBytes = BUF_SIZE; + size_t sWirePubKeyBytes = BUF_SIZE; + size_t sDigestBytes = BUF_SIZE; + size_t sSignatureBytes = BUF_SIZE; + int sRc = 0; + int sIdx = 0; + const char* sPubKeyFile = NULL; + const char* sDigestFile = NULL; + const char* sSigFile = NULL; + bool sPrintHelp = false; + + for(sIdx = 1; sIdx < argc; sIdx++) + { + if(strcmp(argv[sIdx], "-h") == 0) + { + sPrintHelp = true; + } + else if(strcmp(argv[sIdx], "-i") == 0) + { + sIdx++; + sDigestFile = argv[sIdx]; + } + else if(strcmp(argv[sIdx], "-k") == 0) + { + sIdx++; + sPubKeyFile = argv[sIdx]; + } + else if(strcmp(argv[sIdx], "-s") == 0) + { + sIdx++; + sSigFile = argv[sIdx]; + } + else + { + printf("**** ERROR : Unknown parameter : %s\n", argv[sIdx]); + sPrintHelp = true; + } + } + + if(!sPrintHelp && (NULL == sDigestFile || NULL == sPubKeyFile || NULL == sSigFile)) + { + printf("**** ERROR : Missing input parms\n"); + sPrintHelp = true; + } + + if(sPrintHelp) + { + printf("\nverifydilsig -i -k -s \n"); + exit(0); + } + + mlca_ctx_t sCtx; + MLCA_RC sMlRc = 0; + unsigned char* sPubKey = malloc(BUF_SIZE); + unsigned char* sWirePubKey = malloc(BUF_SIZE); + unsigned char* sDigest = malloc(BUF_SIZE); + unsigned char* sSignature = malloc(BUF_SIZE); + + if(!sPubKey || !sWirePubKey || !sDigest || !sSignature) + { + printf("**** ERROR : Allocation Failure\n"); + exit(1); + } + + sRc = readFile(sDigest, &sDigestBytes, sDigestFile); + if(0 == sRc && SHA3_512_DigestSize != sDigestBytes) + { + printf("**** ERROR : %s doesn't appear to be a SHA3-512 digest\n", sDigestFile); + sRc = 1; + } + + if(0 == sRc) + { + sRc = readFile(sWirePubKey, &sWirePubKeyBytes, sPubKeyFile); + } + + if(0 == sRc) + { + sRc = readFile(sSignature, &sSignatureBytes, sSigFile); + } + + if(0 == sRc) + { + // Raw public key size for dilithium r2 8/7 + if(RawDilithiumR28x7PublicKeySize == sWirePubKeyBytes) + { + // Raw key, just copy + memcpy(sPubKey, sWirePubKey, sWirePubKeyBytes); + sPubKeyBytes = sWirePubKeyBytes; + } + else + { + + unsigned int sWireType = 0; + sRc = mlca_wire2key( + sPubKey, sPubKeyBytes, &sWireType, sWirePubKey, sWirePubKeyBytes, NULL, ~0); + if(0 >= sRc) + { + printf("**** ERROR: Unable to convert public key : %d\n", sRc); + sRc = 1; + } + else + { + sPubKeyBytes = sRc; + sRc = 0; + } + } + } + + if(0 == sRc) + { + sMlRc = mlca_init(&sCtx, 1, 0); + if(sMlRc) + { + printf("**** ERROR : Failed mlca_init : %d\n", sMlRc); + sRc = 1; + } + } + if(0 == sRc) + { + sMlRc = mlca_set_alg(&sCtx, MLCA_ALGORITHM_SIG_DILITHIUM_R2_8x7_OID, OPT_LEVEL_AUTO); + if(sMlRc) + { + printf("**** ERROR : Failed mlca_set_alg : %d\n", sMlRc); + sRc = 1; + } + } + if(0 == sRc) + { + sMlRc = mlca_set_encoding_by_idx(&sCtx, 0); + if(sMlRc) + { + printf("**** ERROR : Failed mlca_set_encoding_by_name_oid : %d\n", sMlRc); + sRc = 1; + } + } + if(0 == sRc) + { + printf("Verifying Dilthium R2 8x7 signature ...\n"); + sMlRc = mlca_sig_verify(&sCtx, sDigest, sDigestBytes, sSignature, sSignatureBytes, sPubKey); + if(1 != sMlRc) + { + printf("**** ERROR: Signature verification failure : %d\n", sMlRc); + sRc = 1; + } + } + + free(sDigest); + free(sSignature); + free(sPubKey); + free(sWirePubKey); + mlca_ctx_free(&sCtx); + + exit(sRc); +}