mirror of
https://git.code.sf.net/p/linux-ima/ima-evm-utils
synced 2025-04-28 06:33:36 +02:00
Allow manual setting keyid from a cert file
Allow user to specify `--keyid-from-cert cert.pem' to extract keyid from SKID of the certificate file. PEM or DER format is auto-detected. This commit creates ABI change for libimaevm, due to adding new function ima_read_keyid(). Newer clients cannot work with older libimaevm. Together with previous commit it creates backward-incompatible ABI change, thus soname should be incremented on release. Signed-off-by: Vitaly Chikunov <vt@altlinux.org> Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
This commit is contained in:
parent
51b694bfea
commit
0e7a00e26b
2
README
2
README
@ -49,6 +49,8 @@ OPTIONS
|
|||||||
--rsa use RSA key type and signing scheme v1
|
--rsa use RSA key type and signing scheme v1
|
||||||
-k, --key path to signing key (default: /etc/keys/{privkey,pubkey}_evm.pem)
|
-k, --key path to signing key (default: /etc/keys/{privkey,pubkey}_evm.pem)
|
||||||
--keyid n overwrite signature keyid with a 32-bit value in hex (for signing)
|
--keyid n overwrite signature keyid with a 32-bit value in hex (for signing)
|
||||||
|
--keyid-from-cert file
|
||||||
|
read keyid value from SKID of a x509 cert file
|
||||||
-o, --portable generate portable EVM signatures
|
-o, --portable generate portable EVM signatures
|
||||||
-p, --pass password for encrypted signing key
|
-p, --pass password for encrypted signing key
|
||||||
-r, --recursive recurse into directories (sign)
|
-r, --recursive recurse into directories (sign)
|
||||||
|
14
src/evmctl.c
14
src/evmctl.c
@ -42,6 +42,7 @@
|
|||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -57,12 +58,14 @@
|
|||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <openssl/asn1.h>
|
||||||
#include <openssl/sha.h>
|
#include <openssl/sha.h>
|
||||||
#include <openssl/pem.h>
|
#include <openssl/pem.h>
|
||||||
#include <openssl/hmac.h>
|
#include <openssl/hmac.h>
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
#include <openssl/rsa.h>
|
#include <openssl/rsa.h>
|
||||||
#include <openssl/engine.h>
|
#include <openssl/engine.h>
|
||||||
|
#include <openssl/x509v3.h>
|
||||||
#include "hash_info.h"
|
#include "hash_info.h"
|
||||||
#include "pcr.h"
|
#include "pcr.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
@ -2501,6 +2504,8 @@ static void usage(void)
|
|||||||
" --rsa use RSA key type and signing scheme v1\n"
|
" --rsa use RSA key type and signing scheme v1\n"
|
||||||
" -k, --key path to signing key (default: /etc/keys/{privkey,pubkey}_evm.pem)\n"
|
" -k, --key path to signing key (default: /etc/keys/{privkey,pubkey}_evm.pem)\n"
|
||||||
" --keyid n overwrite signature keyid with a 32-bit value in hex (for signing)\n"
|
" --keyid n overwrite signature keyid with a 32-bit value in hex (for signing)\n"
|
||||||
|
" --keyid-from-cert file\n"
|
||||||
|
" read keyid value from SKID of a x509 cert file\n"
|
||||||
" -o, --portable generate portable EVM signatures\n"
|
" -o, --portable generate portable EVM signatures\n"
|
||||||
" -p, --pass password for encrypted signing key\n"
|
" -p, --pass password for encrypted signing key\n"
|
||||||
" -r, --recursive recurse into directories (sign)\n"
|
" -r, --recursive recurse into directories (sign)\n"
|
||||||
@ -2582,6 +2587,7 @@ static struct option opts[] = {
|
|||||||
{"pcrs", 1, 0, 142},
|
{"pcrs", 1, 0, 142},
|
||||||
{"verify-bank", 2, 0, 143},
|
{"verify-bank", 2, 0, 143},
|
||||||
{"keyid", 1, 0, 144},
|
{"keyid", 1, 0, 144},
|
||||||
|
{"keyid-from-cert", 1, 0, 145},
|
||||||
{}
|
{}
|
||||||
|
|
||||||
};
|
};
|
||||||
@ -2791,6 +2797,14 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
imaevm_params.keyid = keyid;
|
imaevm_params.keyid = keyid;
|
||||||
break;
|
break;
|
||||||
|
case 145:
|
||||||
|
keyid = imaevm_read_keyid(optarg);
|
||||||
|
if (keyid == 0) {
|
||||||
|
log_err("Error reading keyid.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
imaevm_params.keyid = keyid;
|
||||||
|
break;
|
||||||
case '?':
|
case '?':
|
||||||
exit(1);
|
exit(1);
|
||||||
break;
|
break;
|
||||||
|
@ -219,6 +219,7 @@ EVP_PKEY *read_pub_pkey(const char *keyfile, int x509);
|
|||||||
void calc_keyid_v1(uint8_t *keyid, char *str, const unsigned char *pkey, int len);
|
void calc_keyid_v1(uint8_t *keyid, char *str, const unsigned char *pkey, int len);
|
||||||
void calc_keyid_v2(uint32_t *keyid, char *str, EVP_PKEY *pkey);
|
void calc_keyid_v2(uint32_t *keyid, char *str, EVP_PKEY *pkey);
|
||||||
int key2bin(RSA *key, unsigned char *pub);
|
int key2bin(RSA *key, unsigned char *pub);
|
||||||
|
uint32_t imaevm_read_keyid(const char *certfile);
|
||||||
|
|
||||||
int sign_hash(const char *algo, const unsigned char *hash, int size, const char *keyfile, const char *keypass, unsigned char *sig);
|
int sign_hash(const char *algo, const unsigned char *hash, int size, const char *keyfile, const char *keypass, unsigned char *sig);
|
||||||
int verify_hash(const char *file, const unsigned char *hash, int size, unsigned char *sig, int siglen);
|
int verify_hash(const char *file, const unsigned char *hash, int size, unsigned char *sig, int siglen);
|
||||||
|
114
src/libimaevm.c
114
src/libimaevm.c
@ -53,10 +53,12 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include <openssl/asn1.h>
|
||||||
#include <openssl/crypto.h>
|
#include <openssl/crypto.h>
|
||||||
#include <openssl/pem.h>
|
#include <openssl/pem.h>
|
||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
#include <openssl/x509.h>
|
#include <openssl/x509.h>
|
||||||
|
#include <openssl/x509v3.h>
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
|
|
||||||
#include "imaevm.h"
|
#include "imaevm.h"
|
||||||
@ -675,6 +677,118 @@ void calc_keyid_v2(uint32_t *keyid, char *str, EVP_PKEY *pkey)
|
|||||||
X509_PUBKEY_free(pk);
|
X509_PUBKEY_free(pk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extract SKID from x509 in openssl portable way.
|
||||||
|
*/
|
||||||
|
static const unsigned char *x509_get_skid(X509 *x, int *len)
|
||||||
|
{
|
||||||
|
#if OPENSSL_VERSION_NUMBER < 0x10100000
|
||||||
|
ASN1_STRING *skid;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This will cache extensions.
|
||||||
|
* OpenSSL uses this method itself.
|
||||||
|
*/
|
||||||
|
if (X509_check_purpose(x, -1, -1) != 1)
|
||||||
|
return NULL;
|
||||||
|
skid = x->skid;
|
||||||
|
#else
|
||||||
|
const ASN1_OCTET_STRING *skid = X509_get0_subject_key_id(x);
|
||||||
|
#endif
|
||||||
|
if (len)
|
||||||
|
*len = ASN1_STRING_length(skid);
|
||||||
|
#if OPENSSL_VERSION_NUMBER < 0x10100000
|
||||||
|
return ASN1_STRING_data(x->skid);
|
||||||
|
#else
|
||||||
|
return ASN1_STRING_get0_data(skid);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* read_keyid_from_cert() - Read keyid from SKID from x509 certificate file
|
||||||
|
* @keyid_be: Output 32-bit keyid in network order (BE);
|
||||||
|
* @certfile: Input filename.
|
||||||
|
* @try_der: true: try to read in DER from if there is no PEM,
|
||||||
|
* cert is considered mandatory and error will be issued
|
||||||
|
* if there is no cert;
|
||||||
|
* false: only try to read in PEM form, cert is considered
|
||||||
|
* optional.
|
||||||
|
* Return: 0 on success, -1 on error.
|
||||||
|
*/
|
||||||
|
static int read_keyid_from_cert(uint32_t *keyid_be, const char *certfile, int try_der)
|
||||||
|
{
|
||||||
|
X509 *x = NULL;
|
||||||
|
FILE *fp;
|
||||||
|
const unsigned char *skid;
|
||||||
|
int skid_len;
|
||||||
|
|
||||||
|
if (!(fp = fopen(certfile, "r"))) {
|
||||||
|
log_err("Cannot open %s: %s\n", certfile, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!PEM_read_X509(fp, &x, NULL, NULL)) {
|
||||||
|
if (ERR_GET_REASON(ERR_peek_last_error()) == PEM_R_NO_START_LINE) {
|
||||||
|
ERR_clear_error();
|
||||||
|
if (try_der) {
|
||||||
|
rewind(fp);
|
||||||
|
d2i_X509_fp(fp, &x);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Cert is optional and there is just no PEM
|
||||||
|
* header, then issue debug message and stop
|
||||||
|
* trying.
|
||||||
|
*/
|
||||||
|
log_debug("%s: x509 certificate not found\n",
|
||||||
|
certfile);
|
||||||
|
fclose(fp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
if (!x) {
|
||||||
|
ERR_print_errors_fp(stderr);
|
||||||
|
log_err("read keyid: %s: Error reading x509 certificate\n",
|
||||||
|
certfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(skid = x509_get_skid(x, &skid_len))) {
|
||||||
|
log_err("read keyid: %s: SKID not found\n", certfile);
|
||||||
|
goto err_free;
|
||||||
|
}
|
||||||
|
if (skid_len < sizeof(*keyid_be)) {
|
||||||
|
log_err("read keyid: %s: SKID too short (len %d)\n", certfile,
|
||||||
|
skid_len);
|
||||||
|
goto err_free;
|
||||||
|
}
|
||||||
|
memcpy(keyid_be, skid + skid_len - sizeof(*keyid_be), sizeof(*keyid_be));
|
||||||
|
log_info("keyid %04x (from %s)\n", ntohl(*keyid_be), certfile);
|
||||||
|
X509_free(x);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_free:
|
||||||
|
X509_free(x);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* imaevm_read_keyid() - Read 32-bit keyid from the cert file
|
||||||
|
* @certfile: File with certificate in PEM or DER form.
|
||||||
|
*
|
||||||
|
* Try to read keyid from Subject Key Identifier (SKID) of x509 certificate.
|
||||||
|
* Autodetect if cert is in PEM (tried first) or DER encoding.
|
||||||
|
*
|
||||||
|
* Return: 0 on error or 32-bit keyid in host order otherwise.
|
||||||
|
*/
|
||||||
|
uint32_t imaevm_read_keyid(const char *certfile)
|
||||||
|
{
|
||||||
|
uint32_t keyid_be = 0;
|
||||||
|
|
||||||
|
read_keyid_from_cert(&keyid_be, certfile, true);
|
||||||
|
/* On error keyid_be will not be set, returning 0. */
|
||||||
|
return ntohl(keyid_be);
|
||||||
|
}
|
||||||
|
|
||||||
static EVP_PKEY *read_priv_pkey(const char *keyfile, const char *keypass)
|
static EVP_PKEY *read_priv_pkey(const char *keyfile, const char *keypass)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
@ -366,6 +366,7 @@ sign_verify rsa1024 md5 0x030201:K:0080
|
|||||||
sign_verify rsa1024 sha1 0x030202:K:0080
|
sign_verify rsa1024 sha1 0x030202:K:0080
|
||||||
sign_verify rsa1024 sha224 0x030207:K:0080
|
sign_verify rsa1024 sha224 0x030207:K:0080
|
||||||
expect_pass check_sign TYPE=ima KEY=rsa1024 ALG=sha256 PREFIX=0x030204aabbccdd0080 OPTS=--keyid=aabbccdd
|
expect_pass check_sign TYPE=ima KEY=rsa1024 ALG=sha256 PREFIX=0x030204aabbccdd0080 OPTS=--keyid=aabbccdd
|
||||||
|
expect_pass check_sign TYPE=ima KEY=rsa1024 ALG=sha256 PREFIX=0x030204:K:0080 OPTS=--keyid-from-cert=test-rsa1024.cer
|
||||||
sign_verify rsa1024 sha256 0x030204:K:0080
|
sign_verify rsa1024 sha256 0x030204:K:0080
|
||||||
try_different_keys
|
try_different_keys
|
||||||
try_different_sigs
|
try_different_sigs
|
||||||
|
Loading…
x
Reference in New Issue
Block a user