Add sigv3 support for IMA and EVM and all key types
cover Add sigv3 support for IMA and EVM and all key types
This series of patches adds sigv3 support for IMA and EVM for all currently supported key types (RSA, ECDSA, ECRDSA, SM2). evmctl gets a --v3 option for creating the sigv3 signatures and also a --v2 option for creating the old sigv2 signatures. --v2 is still the default.
Some test cases are duplicated to test with --v3.
Regards,
Stefan
Stefan Berger (8):
Implement imaevm_create_sigv3 for creating V3 signatures Implement support for IMA signatures V3 signing scheme Implement support for EVM signatures V3 signing scheme Support v3 IMA and EVM file signatures with --v3 option. Use imaevm_create_sigv3 for fsverity signature creation
tests: Add new --v3 option to sign_verify tests Allow verification of EVM_XATTR_PORTABLE_DIGSIG with sigv3 Allow hashing for sigv3 on EVM_XATTR_PORTABLE_DIGSIG
README | 6 +- src/evmctl.c | 170 ++++++++++++++++++++++++++++------------- src/imaevm.h | 7 ++ src/libimaevm.c | 69 ++++++++++++++++- tests/sign_verify.test | 31 ++++++-- 5 files changed, 221 insertions(+), 62 deletions(-)
Signature · 1 line
2.53.0
PATCH 1/8 Implement imaevm_create_sigv3 for creating V3 signatures
Implement imaevm_create_sigv3 that creates v3 signatures. This function will now also allocate a buffer if the caller did not provide one. Further, it will write the full signature into the signature buffer, including the leading xattr type byte.
--- src/imaevm.h | 7 +++++ src/libimaevm.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 72 insertions(+), 3 deletions(-)
src/imaevm.h +7 -0
@@ -282,4 +282,11 @@ int imaevm_hash_algo_from_sig(unsigned char *sig);const char *imaevm_hash_algo_by_id (int algo);int calc_hash_sigv3 (enum evm_ima_xattr_type type,const char *algo,const unsigned char *in_hash,unsigned char *out_hash); +int imaevm_create_sigv3 (const char *hash_algo,const unsigned char *hash,int size, +const char *keyfile,const char *keypass, +unsigned char **sig,size_t siglen,long sigflags, +enum evm_ima_xattr_type xattr_type, +const struct imaevm_ossl_access *access_info, +uint32_t keyid); +#endif
src/libimaevm.c +65 -3
86 lines not on this page · raw message
Signature · 1 line
2.53.0
PATCH 2/8 Implement support for IMA signatures V3 signing scheme
In reply to Stefan BergerAdd support for creating IMA signatures with the V3 signing scheme. Introduce a global variable that states which signing scheme to use and for now set it to SIGNATURE_V2. Implement the SIGNATURE_V3 case where necessary for IMA.
--- src/evmctl.c | 87 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 67 insertions(+), 20 deletions(-)
src/evmctl.c +67 -20
@@ -123,6 +123,13 @@ static bool hwtpm;static char *g_hash_algo =DEFAULT_HASH_ALGO ;static char *g_keypass; +enum signature_version { +SIGNATURE_V2 =2 , +SIGNATURE_V3 , +}; + +static enum signature_version g_signature_version =SIGNATURE_V2 ; +#define HMAC_FLAG_NO_UUID 0x0001#define HMAC_FLAG_CAPS_SET 0x0002
@@ -652,6 +659,7 @@ static int sign_ima(const char *file, char *hash_algo, const char *key) {unsigned char hash[MAX_DIGEST_SIZE ];unsigned char sig[MAX_SIGNATURE_SIZE ]; +unsigned char *psig;size_t len;int err;
@@ -661,16 +669,35 @@ static int sign_ima(const char *file, char *hash_algo, const char *key) len = (size_t )err;assert (len <=sizeof (hash)); - err =imaevm_signhash (hash_algo, hash, len, key, g_keypass, - sig +1 , sigflags, &access_info, imaevm_keyid); -if (err <=1 ) -return err; - len = (size_t )err; -assert (len <sizeof (sig)); - -/* add header */ - len++; - sig[0 ] =EVM_IMA_XATTR_DIGSIG ; +switch (g_signature_version) { +case SIGNATURE_V3 : + psig = sig; + err =imaevm_create_sigv3 (hash_algo, hash, len, key, g_keypass, + &psig,sizeof (sig), sigflags, +EVM_IMA_XATTR_DIGSIG , &access_info, + imaevm_keyid); +if (err <=1 ) +return err; + len = (size_t )err; +assert (len <=sizeof (sig)); +break ; +case SIGNATURE_V2 : + err =imaevm_signhash (hash_algo, hash, len, key, g_keypass, + sig +1 , sigflags, &access_info, + imaevm_keyid); +if (err <=1 ) +return err; + len = (size_t )err; +assert (len <sizeof (sig)); +/* add header */ + len++; + sig[0 ] =EVM_IMA_XATTR_DIGSIG ; +break ; +default : +log_err ("Internal error: Unsupported signature version: %d\n" , + g_signature_version); +return -1 ; + }if (sigdump || imaevm_params.verbose >=LOG_INFO )imaevm_hexdump (sig, len);
@@ -791,6 +818,7 @@ static int cmd_sign_hash(struct command *cmd)size_t hashlen =0 ;int siglen;char *line =NULL , *token, *hashp; +unsigned char *psig;size_t line_len =0 ;const char *key;char algo[7 ];/* Current maximum fsverity hash algo name length */
@@ -863,20 +891,39 @@ static int cmd_sign_hash(struct command *cmd)assert (hashlen /2 <=sizeof (hash));hex2bin (hash, line, hashlen /2 ); - siglen =imaevm_signhash (g_hash_algo, hash, - hashlen /2 , key, g_keypass, - sig +1 , sigflags, - &access_info, imaevm_keyid); - sig[0 ] =EVM_IMA_XATTR_DIGSIG ; +switch (g_signature_version) { +case SIGNATURE_V3 : + psig = sig; + siglen =imaevm_create_sigv3 (g_hash_algo, hash, + hashlen /2 , key, g_keypass, + &psig,sizeof (sig), sigflags, +EVM_IMA_XATTR_DIGSIG , + &access_info, imaevm_keyid); +if (siglen <=1 ) +return siglen; +assert (siglen <= (int )sizeof (sig)); +break ; +case SIGNATURE_V2 : + siglen =imaevm_signhash (g_hash_algo, hash, + hashlen /2 , key, g_keypass, + sig +1 , sigflags, + &access_info, imaevm_keyid); +if (siglen <=1 ) +return siglen; +assert (siglen < (int )sizeof (sig)); + siglen++; + sig[0 ] =EVM_IMA_XATTR_DIGSIG ; +break ; +default : +log_err ("Internal error: Unsupported signature version: %d\n" , + g_signature_version); +return -1 ; + } } -if (siglen <=1 ) -return siglen; -assert (siglen < (int )sizeof (sig)); -fwrite (line, len,1 , stdout);fprintf (stdout," " ); -bin2hex (sig, siglen +1 , stdout); +bin2hex (sig, siglen, stdout);fprintf (stdout,"\n" ); }
Signature · 1 line
2.53.0
PATCH 3/8 Implement support for EVM signatures V3 signing scheme
In reply to Stefan BergerAdd support for creating EVM signatures with the V3 signing scheme. Implement the SIGNATURE_v3 case where necessary for EVM.
--- src/evmctl.c | 45 +++++++++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 14 deletions(-)
src/evmctl.c +31 -14
@@ -564,8 +564,10 @@ out:static int sign_evm (const char *file,char *hash_algo,const char *key) { -unsigned char hash[MAX_DIGEST_SIZE ];unsigned char sig[MAX_SIGNATURE_SIZE ]; +unsigned char hash[MAX_DIGEST_SIZE ]; +enum evm_ima_xattr_type xattr_type; +unsigned char *psig;size_t len;int err;
@@ -575,22 +577,37 @@ static int sign_evm(const char *file, char *hash_algo, const char *key) len = (size_t )err;assert (len <=sizeof (hash)); - err =imaevm_signhash (hash_algo, hash, len, key, g_keypass, - sig +1 , sigflags, &access_info, imaevm_keyid); -if (err <=1 ) -return err; - len = (size_t )err; -assert (len <=sizeof (sig)); - -/* add header */ - len++;if (evm_portable) - sig[0 ] =EVM_XATTR_PORTABLE_DIGSIG ; + xattr_type =EVM_XATTR_PORTABLE_DIGSIG ;else - sig[0 ] =EVM_IMA_XATTR_DIGSIG ; + xattr_type =EVM_IMA_XATTR_DIGSIG ; -if (evm_immutable) - sig[1 ] =3 ;/* immutable signature version */ +switch (g_signature_version) { +case SIGNATURE_V3 : + psig = sig; + err =imaevm_create_sigv3 (hash_algo, hash, len, key, g_keypass, + &psig,sizeof (sig), sigflags, + xattr_type, &access_info, + imaevm_keyid); +if (err <=1 ) +return err; + len = (size_t )err; +assert (len <=sizeof (sig)); +break ; +case SIGNATURE_V2 : + err =imaevm_signhash (hash_algo, hash, len, key, g_keypass, + sig +1 , sigflags, &access_info, imaevm_keyid); +if (err <=1 ) +return err; + len = (size_t )err; +assert (len <=sizeof (sig)); +/* add header */ + len++; + sig[0 ] = xattr_type; +if (evm_immutable) + sig[1 ] =3 ;/* immutable signature version */ +break ; + }if (sigdump || imaevm_params.verbose >=LOG_INFO )imaevm_hexdump (sig, len);
Signature · 1 line
2.53.0
PATCH 4/8 Support v3 IMA and EVM file signatures with --v3 option.
In reply to Stefan BergerEnable both IMA and EVM file signatures with a new --v3 option that sets the previously introduced global variable that states which signature version to use.
Similarly, introduce a --v2 option for users to (already) choose old V2 type of signatures.
Update the README with the dump of the evmctl help screen and mention v3 signature format that is expected for Linux 7.1.
--- README | 6 ++++-- src/evmctl.c | 10 ++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-)
README +4 -2
@@ -84,6 +84,8 @@ OPTIONS --provider p preload OpenSSL provider (such as: pkcs11) --ignore-violations ignore ToMToU measurement violations --hmackey path to symmetric key (default: /etc/keys/evm-key-plain) + --v2 create V2 signatures; this is the default + --v3 create V3 signatures; this requires Linux 7.1 or later -v increase verbosity level -h, --help display this help and exit
@@ -139,7 +141,7 @@ evmctl '--smack' options enables that. Key and signature formats ------------------------- -Linux integrity subsystem supports two type of signature and respectively two +Linux integrity subsystem supports three types of signature and respectively two key formats. First key format (v1) is pure RSA key encoded in PEM a format and uses own signature
@@ -149,7 +151,7 @@ for signing and importing the key. Second key format uses X509 DER encoded public key certificates and uses asymmetric key support in the kernel (since kernel 3.9). CONFIG_INTEGRITY_ASYMMETRIC_KEYS must be enabled (default). -For v2 signatures x509 certificate (containing the public key) could be appended to the +For v2 and v3 signatures x509 certificate (containing the public key) could be appended to the private key (they both are in PEM format) to automatically extract keyid from its Subject Key Identifier (SKID).
src/evmctl.c +10 -0
@@ -3017,6 +3017,8 @@ static void usage(void)#ifdef DEBUG " --hmackey path to symmetric key (default: /etc/keys/evm-key-plain)\n"#endif +" --v2 create V2 signatures; this is the default\n" +" --v3 create V3 signatures; this requires Linux 7.1 or later\n" " -v increase verbosity level\n" " -h, --help display this help and exit\n" "\n"
@@ -3092,6 +3094,8 @@ static struct option opts[] = { #if CONFIG_IMA_EVM_PROVIDER {"provider", 1, 0, 149}, #endif + {"v2", 0, 0, 150}, + {"v3", 0, 0, 151}, {} };
@@ -3370,6 +3374,12 @@ int main(int argc, char *argv[]) access_info.type =IMAEVM_OSSL_ACCESS_TYPE_PROVIDER ;break ;#endif +case 150 :/* --v2 */ + g_signature_version =SIGNATURE_V2 ; +break ; +case 151 :/* --v3 */ + g_signature_version =SIGNATURE_V3 ; +break ;case '?' :exit (1 );break ;
Signature · 1 line
2.53.0
PATCH 5/8 Use imaevm_create_sigv3 for fsverity signature creation
In reply to Stefan BergerConvert the code that built the fsverity signature with V3 signing scheme to use the new imaevm_create_sigv3 function.
--- src/evmctl.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-)
src/evmctl.c +9 -15
@@ -828,7 +828,6 @@ static int cmd_sign_ima(struct command *cmd)*/ static int cmd_sign_hash (struct command *cmd) { -unsigned char sigv3_hash[MAX_DIGEST_SIZE ];unsigned char sig[MAX_SIGNATURE_SIZE ];unsigned char hash[MAX_DIGEST_SIZE ];size_t algolen =0 ;
@@ -840,7 +839,6 @@ static int cmd_sign_hash(struct command *cmd)const char *key;char algo[7 ];/* Current maximum fsverity hash algo name length */ ssize_t len; -int ret; key = imaevm_params.keyfile ? :"/etc/keys/privkey_evm.pem" ;
@@ -888,19 +886,15 @@ static int cmd_sign_hash(struct command *cmd)assert (hashlen /2 <=sizeof (hash));hex2bin (hash, hashp, hashlen /2 ); - ret =calc_hash_sigv3 (IMA_VERITY_DIGSIG , algo, hash, - sigv3_hash); -if (ret <0 || ret ==1 ) { -log_info ("Failure to calculate fs-verity hash\n" ); -continue ; - } - - siglen =imaevm_signhash (algo, sigv3_hash, hashlen /2 , - key, g_keypass, sig +1 , sigflags, - &access_info, imaevm_keyid); - - sig[0 ] =IMA_VERITY_DIGSIG ; - sig[1 ] =DIGSIG_VERSION_3 ;/* sigv3 */ + psig = sig; + siglen =imaevm_create_sigv3 (algo, hash, + hashlen /2 , key, g_keypass, + &psig,sizeof (sig), sigflags, +IMA_VERITY_DIGSIG , + &access_info, imaevm_keyid); +if (siglen <=1 ) +return siglen; +assert (siglen <= (int )sizeof (sig)); }else {/* Parse the shaXsum output */ token =strpbrk (line," \t" );
Signature · 1 line
2.53.0
PATCH 6/8 tests: Add new --v3 option to sign_verify tests
In reply to Stefan BergerAdd the new --v3 option to the sign_verify test cases.
For --v3, adjust openssl signature verification to build an ima_file_id structure in a file that is then used for signature verification rather than the plain file (as before).
--- tests/sign_verify.test | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-)
tests/sign_verify.test +25 -6
@@ -128,7 +128,7 @@ check_sign() { # OPTS (additional options for evmctl), # FILE (working file to sign). local "$@" - local key verifykey + local key verifykey sigver local FILE=${FILE:-$ALG.txt} # Normalize key filename if it's not a pkcs11 URI
@@ -213,18 +213,30 @@ check_sign() { verifykey=${key} fi - cmd="openssl dgst $OPENSSL_ENGINE $OPENSSL_KEYFORM -$ALG -verify ${verifykey} \ - -signature $FILE.sig2 $FILE" + if [[ "$OPTS" =~ "--v3" ]]; then + # In case of v3 signatures we need to create ima_file_id now. + # All data for it can be found in PREFIX and by hashing $FILE. + echo -en "\x${PREFIX:2:2}\x${PREFIX:6:2}" > "$FILE.tmp" + # shellcheck disable=SC2086 + openssl dgst $OPENSSL_ENGINE $OPENSSL_KEYFORM -"$ALG" -binary "$FILE" >> "$FILE.tmp" + cmd="openssl dgst $OPENSSL_ENGINE $OPENSSL_KEYFORM -$ALG -verify ${verifykey} \ + -signature $FILE.sig2 $FILE.tmp" + sigver=3 + else + cmd="openssl dgst $OPENSSL_ENGINE $OPENSSL_KEYFORM -$ALG -verify ${verifykey} \ + -signature $FILE.sig2 $FILE" + sigver=2 + fi echo - "$cmd" if ! $cmd; then color_red_on_failure - echo "Signature v2 verification with openssl is failed." + echo "Signature v${sigver} verification with openssl is failed." color_restore - rm "$FILE.sig2" + rm "$FILE.sig2" "$FILE.tmp" return "$FAIL" fi - rm "$FILE.sig2" + rm "$FILE.sig2" "$FILE.tmp" return "$OK" }
@@ -390,6 +402,9 @@ sign_verify rsa1024 sha384 0x030205:K:0080 sign_verify rsa1024 sha512 0x030206:K:0080 sign_verify rsa1024 rmd160 0x030203:K:0080 +sign_verify rsa1024 sha384 0x030305:K:0080 --v3 +sign_verify rsa1024 sha512 0x030306:K:0080 --v3 + # Test v2 signatures with ECDSA # Signature length is typically 0x34-0x38 bytes long, very rarely 0x33 sign_verify prime192v1 sha1 0x030202:K:003[345678]
@@ -405,6 +420,10 @@ sign_verify prime256v1 sha256 0x030204:K:004[345678] sign_verify prime256v1 sha384 0x030205:K:004[345678] sign_verify prime256v1 sha512 0x030206:K:004[345678] +sign_verify prime256v1 sha256 0x030304:K:004[345678] --v3 +sign_verify prime256v1 sha384 0x030305:K:004[345678] --v3 +sign_verify prime256v1 sha512 0x030306:K:004[345678] --v3 + # If openssl 3.0 is installed, test the SM2/3 algorithm combination ssl_major_version=$(openssl version | sed -n 's/^OpenSSL \([^\.]\).*/\1/p') if [ "${ssl_major_version}" = 3 ]; then
Signature · 1 line
2.53.0
PATCH 7/8 Allow verification of EVM_XATTR_PORTABLE_DIGSIG with sigv3
In reply to Stefan BergerTo enable sigv3 signature verification for EVM portable signatures, allow signature verification on EVM_XATTR_PORTABLE_DIGSIG type of xattrs with sigv3.
--- src/evmctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
src/evmctl.c +1 -1
@@ -995,7 +995,7 @@ static int verify_evm(struct public_key_entry *public_keys, const char *file) }if (sig[0 ] ==EVM_XATTR_PORTABLE_DIGSIG ) { -if (sig[1 ] !=DIGSIG_VERSION_2 ) { +if (sig[1 ] !=DIGSIG_VERSION_2 && sig[1 ] !=DIGSIG_VERSION_3 ) {log_err ("Portable sig: invalid type\n" );return -1 ; }
Signature · 1 line
2.53.0
PATCH 8/8 Allow hashing for sigv3 on EVM_XATTR_PORTABLE_DIGSIG
In reply to Stefan BergerTo enable sigv3 for EVM portable signatures, enable hashing for sigv3 for EVM_XATTR_PORTABLE_DIGSIG.
--- src/libimaevm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
src/libimaevm.c +2 -1
@@ -623,7 +623,8 @@ int calc_hash_sigv3(enum evm_ima_xattr_type type, const char *algo,unsigned int unused;if (type !=IMA_VERITY_DIGSIG && - type !=EVM_IMA_XATTR_DIGSIG ) { + type !=EVM_IMA_XATTR_DIGSIG && + type !=EVM_XATTR_PORTABLE_DIGSIG ) {log_err ("Only fsverity and IMA/EVM support signature format v3 (sigv3)\n" );return -EINVAL ; }
Signature · 1 line
2.53.0