Message ID | 20190215041340.29258-1-stefan.strogin@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | libkmod-signature: use PKCS7 for LibreSSL or older OpenSSL | expand |
On Fri, Feb 15, 2019 at 06:13:40AM +0200, Stefan Strogin wrote: >Linux kernel uses either PKCS #7 or CMS signing modules (scripts/sign-file.c). >CMS is not supported by LibreSSL, PKCS #7 is used instead. >For now modinfo used CMS with no altenative requiring >=openssl-1.1.0 >built with CMS support. > >Use PKCS #7 for parsing module signature information when CMS is not available. > >Signed-off-by: Stefan Strogin <stefan.strogin@gmail.com> ooh, this ifdef is messy. Why do we want both libressl and openssl? What distro is requiring that? if in the end we end up with ifdefs for N different libs I'd rather just add the implementation in kmod itself or convince kernel guys to just fill out the struct they are supposed to fill. Lucas De Marchi >--- > libkmod/libkmod-signature.c | 78 +++++++++++++++++++++++++++++++++++-- > 1 file changed, 75 insertions(+), 3 deletions(-) > >diff --git a/libkmod/libkmod-signature.c b/libkmod/libkmod-signature.c >index 48d0145..aa2a60e 100644 >--- a/libkmod/libkmod-signature.c >+++ b/libkmod/libkmod-signature.c >@@ -20,9 +20,16 @@ > #include <endian.h> > #include <inttypes.h> > #ifdef ENABLE_OPENSSL >-#include <openssl/cms.h> >-#include <openssl/ssl.h> >-#endif >+# include <openssl/ssl.h> >+# if defined(LIBRESSL_VERSION_NUMBER) || \ >+ OPENSSL_VERSION_NUMBER < 0x10100000L || \ >+ defined(OPENSSL_NO_CMS) >+# define USE_PKCS7 >+# include <openssl/pkcs7.h> >+# else >+# include <openssl/cms.h> >+# endif /* LIBRESSL_VERSION_NUMBER */ >+#endif /* ENABLE_OPENSSL */ > #include <stdio.h> > #include <stdlib.h> > #include <string.h> >@@ -122,7 +129,11 @@ static bool fill_default(const char *mem, off_t size, > #ifdef ENABLE_OPENSSL > > struct pkcs7_private { >+#ifndef USE_PKCS7 > CMS_ContentInfo *cms; >+#else >+ PKCS7 *pkcs7; >+#endif > unsigned char *key_id; > BIGNUM *sno; > }; >@@ -132,7 +143,11 @@ static void pkcs7_free(void *s) > struct kmod_signature_info *si = s; > struct pkcs7_private *pvt = si->private; > >+#ifndef USE_PKCS7 > CMS_ContentInfo_free(pvt->cms); >+#else >+ PKCS7_free(pvt->pkcs7); >+#endif > BN_free(pvt->sno); > free(pvt->key_id); > free(pvt); >@@ -187,7 +202,13 @@ static const char *x509_name_to_str(X509_NAME *name) > return NULL; > > d = X509_NAME_ENTRY_get_data(e); >+#if (defined(LIBRESSL_VERSION_NUMBER) && \ >+ LIBRESSL_VERSION_NUMBER < 0x20700000L) || \ >+ OPENSSL_VERSION_NUMBER < 0x10100000L >+ str = (const char *)ASN1_STRING_data(d); >+#else > str = (const char *)ASN1_STRING_get0_data(d); >+#endif > > return str; > } >@@ -197,11 +218,18 @@ static bool fill_pkcs7(const char *mem, off_t size, > struct kmod_signature_info *sig_info) > { > const char *pkcs7_raw; >+#ifndef USE_PKCS7 > CMS_ContentInfo *cms; > STACK_OF(CMS_SignerInfo) *sis; > CMS_SignerInfo *si; > int rc; > ASN1_OCTET_STRING *key_id; >+#else >+ PKCS7 *pkcs7; >+ STACK_OF(PKCS7_SIGNER_INFO) *sis; >+ PKCS7_SIGNER_INFO *si; >+ PKCS7_ISSUER_AND_SERIAL *is; >+#endif > X509_NAME *issuer; > ASN1_INTEGER *sno; > ASN1_OCTET_STRING *sig; >@@ -220,14 +248,23 @@ static bool fill_pkcs7(const char *mem, off_t size, > > in = BIO_new_mem_buf(pkcs7_raw, sig_len); > >+#ifndef USE_PKCS7 > cms = d2i_CMS_bio(in, NULL); > if (cms == NULL) { > BIO_free(in); > return false; > } >+#else >+ pkcs7 = d2i_PKCS7_bio(in, NULL); >+ if (pkcs7 == NULL) { >+ BIO_free(in); >+ return false; >+ } >+#endif > > BIO_free(in); > >+#ifndef USE_PKCS7 > sis = CMS_get0_SignerInfos(cms); > if (sis == NULL) > goto err; >@@ -245,8 +282,35 @@ static bool fill_pkcs7(const char *mem, off_t size, > goto err; > > CMS_SignerInfo_get0_algs(si, NULL, NULL, &dig_alg, &sig_alg); >+#else >+ sis = PKCS7_get_signer_info(pkcs7); >+ if (sis == NULL) >+ goto err; >+ >+ si = sk_PKCS7_SIGNER_INFO_value(sis, 0); >+ if (si == NULL) >+ goto err; >+ >+ is = si->issuer_and_serial; >+ if (is == NULL) >+ goto err; >+ issuer = is->issuer; >+ sno = is->serial; >+ >+ sig = si->enc_digest; >+ if (sig == NULL) >+ goto err; >+ >+ PKCS7_SIGNER_INFO_get0_algs(si, NULL, &dig_alg, &sig_alg); >+#endif > >+#if (defined(LIBRESSL_VERSION_NUMBER) && \ >+ LIBRESSL_VERSION_NUMBER < 0x20700000L) || \ >+ OPENSSL_VERSION_NUMBER < 0x10100000L >+ sig_info->sig = (const char *)ASN1_STRING_data(sig); >+#else > sig_info->sig = (const char *)ASN1_STRING_get0_data(sig); >+#endif > sig_info->sig_len = ASN1_STRING_length(sig); > > sno_bn = ASN1_INTEGER_to_BN(sno, NULL); >@@ -277,7 +341,11 @@ static bool fill_pkcs7(const char *mem, off_t size, > if (pvt == NULL) > goto err3; > >+#ifndef USE_PKCS7 > pvt->cms = cms; >+#else >+ pvt->pkcs7 = pkcs7; >+#endif > pvt->key_id = key_id_str; > pvt->sno = sno_bn; > sig_info->private = pvt; >@@ -290,7 +358,11 @@ err3: > err2: > BN_free(sno_bn); > err: >+#ifndef USE_PKCS7 > CMS_ContentInfo_free(cms); >+#else >+ PKCS7_free(pkcs7); >+#endif > return false; > } > >-- >2.20.1 >
On 15/02/2019 10:04, Lucas De Marchi wrote: > > ooh, this ifdef is messy. Why do we want both libressl and openssl? What > distro is requiring that? Well, in the kernel in scripts/sign-file.c the same ifdefs are used. Every distro that tries to support LibreSSL requires that. I know at least Gentoo [1], Alpine and Void. > if in the end we end up with ifdefs for N different libs I'd rather just > add the implementation in kmod itself or convince kernel guys to just > fill out the struct they are supposed to fill. If you don't like ifdefs at all I would say that CMS is not needed. CMS and PKCS#7 formats are very similar. CMS is newer but is as much as possible backward compatible [2], but PKCS#7 is better supported. PKCS#7 has all the same fields that are used when a kernel module is signed using CMS (and otherwise). For example I can sign a module using OpenSSL-1.1.1 and CMS (even with hashes other than sha1) and read its signing information with modinfo and PKCS#7 on a system with LibreSSL, and otherwise. So we can just replace CMS with PKCS#7 in fill_pkcs7(). [1] https://bugs.gentoo.org/677960 [2] https://tools.ietf.org/html/rfc5652#section-1.1 -- Stefan
Hi Lucas, Is there any chance for accepting this patch? Or could you tell me how it can be reworked so that modinfo would support PKCS#7 (and LibreSSL)? -- Stefan On 15/02/2019 15:30, Stefan Strogin wrote: > On 15/02/2019 10:04, Lucas De Marchi wrote: >> >> ooh, this ifdef is messy. Why do we want both libressl and openssl? What >> distro is requiring that? > > Well, in the kernel in scripts/sign-file.c the same ifdefs are used. > > Every distro that tries to support LibreSSL requires that. I know at least > Gentoo [1], Alpine and Void. > >> if in the end we end up with ifdefs for N different libs I'd rather just >> add the implementation in kmod itself or convince kernel guys to just >> fill out the struct they are supposed to fill. > > If you don't like ifdefs at all I would say that CMS is not needed. CMS and > PKCS#7 formats are very similar. CMS is newer but is as much as possible > backward compatible [2], but PKCS#7 is better supported. PKCS#7 has all the same > fields that are used when a kernel module is signed using CMS (and otherwise). > For example I can sign a module using OpenSSL-1.1.1 and CMS (even with hashes > other than sha1) and read its signing information with modinfo and PKCS#7 on a > system with LibreSSL, and otherwise. > > So we can just replace CMS with PKCS#7 in fill_pkcs7(). > > [1] https://bugs.gentoo.org/677960 > [2] https://tools.ietf.org/html/rfc5652#section-1.1 > > -- > Stefan >
diff --git a/libkmod/libkmod-signature.c b/libkmod/libkmod-signature.c index 48d0145..aa2a60e 100644 --- a/libkmod/libkmod-signature.c +++ b/libkmod/libkmod-signature.c @@ -20,9 +20,16 @@ #include <endian.h> #include <inttypes.h> #ifdef ENABLE_OPENSSL -#include <openssl/cms.h> -#include <openssl/ssl.h> -#endif +# include <openssl/ssl.h> +# if defined(LIBRESSL_VERSION_NUMBER) || \ + OPENSSL_VERSION_NUMBER < 0x10100000L || \ + defined(OPENSSL_NO_CMS) +# define USE_PKCS7 +# include <openssl/pkcs7.h> +# else +# include <openssl/cms.h> +# endif /* LIBRESSL_VERSION_NUMBER */ +#endif /* ENABLE_OPENSSL */ #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -122,7 +129,11 @@ static bool fill_default(const char *mem, off_t size, #ifdef ENABLE_OPENSSL struct pkcs7_private { +#ifndef USE_PKCS7 CMS_ContentInfo *cms; +#else + PKCS7 *pkcs7; +#endif unsigned char *key_id; BIGNUM *sno; }; @@ -132,7 +143,11 @@ static void pkcs7_free(void *s) struct kmod_signature_info *si = s; struct pkcs7_private *pvt = si->private; +#ifndef USE_PKCS7 CMS_ContentInfo_free(pvt->cms); +#else + PKCS7_free(pvt->pkcs7); +#endif BN_free(pvt->sno); free(pvt->key_id); free(pvt); @@ -187,7 +202,13 @@ static const char *x509_name_to_str(X509_NAME *name) return NULL; d = X509_NAME_ENTRY_get_data(e); +#if (defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER < 0x20700000L) || \ + OPENSSL_VERSION_NUMBER < 0x10100000L + str = (const char *)ASN1_STRING_data(d); +#else str = (const char *)ASN1_STRING_get0_data(d); +#endif return str; } @@ -197,11 +218,18 @@ static bool fill_pkcs7(const char *mem, off_t size, struct kmod_signature_info *sig_info) { const char *pkcs7_raw; +#ifndef USE_PKCS7 CMS_ContentInfo *cms; STACK_OF(CMS_SignerInfo) *sis; CMS_SignerInfo *si; int rc; ASN1_OCTET_STRING *key_id; +#else + PKCS7 *pkcs7; + STACK_OF(PKCS7_SIGNER_INFO) *sis; + PKCS7_SIGNER_INFO *si; + PKCS7_ISSUER_AND_SERIAL *is; +#endif X509_NAME *issuer; ASN1_INTEGER *sno; ASN1_OCTET_STRING *sig; @@ -220,14 +248,23 @@ static bool fill_pkcs7(const char *mem, off_t size, in = BIO_new_mem_buf(pkcs7_raw, sig_len); +#ifndef USE_PKCS7 cms = d2i_CMS_bio(in, NULL); if (cms == NULL) { BIO_free(in); return false; } +#else + pkcs7 = d2i_PKCS7_bio(in, NULL); + if (pkcs7 == NULL) { + BIO_free(in); + return false; + } +#endif BIO_free(in); +#ifndef USE_PKCS7 sis = CMS_get0_SignerInfos(cms); if (sis == NULL) goto err; @@ -245,8 +282,35 @@ static bool fill_pkcs7(const char *mem, off_t size, goto err; CMS_SignerInfo_get0_algs(si, NULL, NULL, &dig_alg, &sig_alg); +#else + sis = PKCS7_get_signer_info(pkcs7); + if (sis == NULL) + goto err; + + si = sk_PKCS7_SIGNER_INFO_value(sis, 0); + if (si == NULL) + goto err; + + is = si->issuer_and_serial; + if (is == NULL) + goto err; + issuer = is->issuer; + sno = is->serial; + + sig = si->enc_digest; + if (sig == NULL) + goto err; + + PKCS7_SIGNER_INFO_get0_algs(si, NULL, &dig_alg, &sig_alg); +#endif +#if (defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER < 0x20700000L) || \ + OPENSSL_VERSION_NUMBER < 0x10100000L + sig_info->sig = (const char *)ASN1_STRING_data(sig); +#else sig_info->sig = (const char *)ASN1_STRING_get0_data(sig); +#endif sig_info->sig_len = ASN1_STRING_length(sig); sno_bn = ASN1_INTEGER_to_BN(sno, NULL); @@ -277,7 +341,11 @@ static bool fill_pkcs7(const char *mem, off_t size, if (pvt == NULL) goto err3; +#ifndef USE_PKCS7 pvt->cms = cms; +#else + pvt->pkcs7 = pkcs7; +#endif pvt->key_id = key_id_str; pvt->sno = sno_bn; sig_info->private = pvt; @@ -290,7 +358,11 @@ err3: err2: BN_free(sno_bn); err: +#ifndef USE_PKCS7 CMS_ContentInfo_free(cms); +#else + PKCS7_free(pkcs7); +#endif return false; }
Linux kernel uses either PKCS #7 or CMS signing modules (scripts/sign-file.c). CMS is not supported by LibreSSL, PKCS #7 is used instead. For now modinfo used CMS with no altenative requiring >=openssl-1.1.0 built with CMS support. Use PKCS #7 for parsing module signature information when CMS is not available. Signed-off-by: Stefan Strogin <stefan.strogin@gmail.com> --- libkmod/libkmod-signature.c | 78 +++++++++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 3 deletions(-)