Message ID | 20201126184110.30521-10-sughosh.ganu@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | qemu: arm64: Add support for uefi capsule update on qemu arm64 platform | expand |
On 11/26/20 7:41 PM, Sughosh Ganu wrote: > The pkcs7 header parsing functionality is pretty generic, and can be > used by other features like capsule authentication. Make the function > an extern, also changing it's name to efi_parse_pkcs7_header > > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org> > --- > include/efi_loader.h | 4 ++ > lib/efi_loader/efi_signature.c | 85 +++++++++++++++++++++++++++++++ > lib/efi_loader/efi_variable.c | 93 ++-------------------------------- > 3 files changed, 93 insertions(+), 89 deletions(-) > > diff --git a/include/efi_loader.h b/include/efi_loader.h > index 76cd2b36f2..b9226208f5 100644 > --- a/include/efi_loader.h > +++ b/include/efi_loader.h > @@ -810,6 +810,10 @@ bool efi_secure_boot_enabled(void); > bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp, > WIN_CERTIFICATE **auth, size_t *auth_len); > > +struct pkcs7_message *efi_parse_pkcs7_header(const void *buf, > + size_t buflen, > + u8 **tmpbuf); > + > /* runtime implementation of memcpy() */ > void efi_memcpy_runtime(void *dest, const void *src, size_t n); > > diff --git a/lib/efi_loader/efi_signature.c b/lib/efi_loader/efi_signature.c > index 79dee27421..9ab071b611 100644 > --- a/lib/efi_loader/efi_signature.c > +++ b/lib/efi_loader/efi_signature.c > @@ -27,6 +27,91 @@ const efi_guid_t efi_guid_cert_x509_sha256 = EFI_CERT_X509_SHA256_GUID; > const efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID; > > #ifdef CONFIG_EFI_SECURE_BOOT > +static u8 pkcs7_hdr[] = { > + /* SEQUENCE */ > + 0x30, 0x82, 0x05, 0xc7, > + /* OID: pkcs7-signedData */ > + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, > + /* Context Structured? */ > + 0xa0, 0x82, 0x05, 0xb8, Dear Takahiro, From where are these magic numbers taken? Could you, please, provide a reference that we can add as a comment. Best regards Heinrich > +}; > + > +/** > + * efi_parse_pkcs7_header - parse a signature in payload > + * @buf: Pointer to payload's value > + * @buflen: Length of @buf > + * @tmpbuf: Pointer to temporary buffer > + * > + * Parse a signature embedded in payload's value and instantiate > + * a pkcs7_message structure. Since pkcs7_parse_message() accepts only > + * pkcs7's signedData, some header needed be prepended for correctly > + * parsing authentication data > + * A temporary buffer will be allocated if needed, and it should be > + * kept valid during the authentication because some data in the buffer > + * will be referenced by efi_signature_verify(). > + * > + * Return: Pointer to pkcs7_message structure on success, NULL on error > + */ > +struct pkcs7_message *efi_parse_pkcs7_header(const void *buf, > + size_t buflen, > + u8 **tmpbuf) > +{ > + u8 *ebuf; > + size_t ebuflen, len; > + struct pkcs7_message *msg; > + > + /* > + * This is the best assumption to check if the binary is > + * already in a form of pkcs7's signedData. > + */ > + if (buflen > sizeof(pkcs7_hdr) && > + !memcmp(&((u8 *)buf)[4], &pkcs7_hdr[4], 11)) { > + msg = pkcs7_parse_message(buf, buflen); > + if (IS_ERR(msg)) > + return NULL; > + return msg; > + } > + > + /* > + * Otherwise, we should add a dummy prefix sequence for pkcs7 > + * message parser to be able to process. > + * NOTE: EDK2 also uses similar hack in WrapPkcs7Data() > + * in CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyCommon.c > + * TODO: > + * The header should be composed in a more refined manner. > + */ > + EFI_PRINT("Makeshift prefix added to authentication data\n"); > + ebuflen = sizeof(pkcs7_hdr) + buflen; > + if (ebuflen <= 0x7f) { > + EFI_PRINT("Data is too short\n"); > + return NULL; > + } > + > + ebuf = malloc(ebuflen); > + if (!ebuf) { > + EFI_PRINT("Out of memory\n"); > + return NULL; > + } > + > + memcpy(ebuf, pkcs7_hdr, sizeof(pkcs7_hdr)); > + memcpy(ebuf + sizeof(pkcs7_hdr), buf, buflen); > + len = ebuflen - 4; > + ebuf[2] = (len >> 8) & 0xff; > + ebuf[3] = len & 0xff; > + len = ebuflen - 0x13; > + ebuf[0x11] = (len >> 8) & 0xff; > + ebuf[0x12] = len & 0xff; > + > + msg = pkcs7_parse_message(ebuf, ebuflen); > + > + if (IS_ERR(msg)) { > + free(ebuf); > + return NULL; > + } > + > + *tmpbuf = ebuf; > + return msg; > +} > > /** > * efi_hash_regions - calculate a hash value > diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c > index 0c689cfb47..ba0874e9e7 100644 > --- a/lib/efi_loader/efi_variable.c > +++ b/lib/efi_loader/efi_variable.c > @@ -24,91 +24,6 @@ > #include <asm/sections.h> > > #ifdef CONFIG_EFI_SECURE_BOOT > -static u8 pkcs7_hdr[] = { > - /* SEQUENCE */ > - 0x30, 0x82, 0x05, 0xc7, > - /* OID: pkcs7-signedData */ > - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, > - /* Context Structured? */ > - 0xa0, 0x82, 0x05, 0xb8, > -}; > - > -/** > - * efi_variable_parse_signature - parse a signature in variable > - * @buf: Pointer to variable's value > - * @buflen: Length of @buf > - * @tmpbuf: Pointer to temporary buffer > - * > - * Parse a signature embedded in variable's value and instantiate > - * a pkcs7_message structure. Since pkcs7_parse_message() accepts only > - * pkcs7's signedData, some header needed be prepended for correctly > - * parsing authentication data, particularly for variable's. > - * A temporary buffer will be allocated if needed, and it should be > - * kept valid during the authentication because some data in the buffer > - * will be referenced by efi_signature_verify(). > - * > - * Return: Pointer to pkcs7_message structure on success, NULL on error > - */ > -static struct pkcs7_message *efi_variable_parse_signature(const void *buf, > - size_t buflen, > - u8 **tmpbuf) > -{ > - u8 *ebuf; > - size_t ebuflen, len; > - struct pkcs7_message *msg; > - > - /* > - * This is the best assumption to check if the binary is > - * already in a form of pkcs7's signedData. > - */ > - if (buflen > sizeof(pkcs7_hdr) && > - !memcmp(&((u8 *)buf)[4], &pkcs7_hdr[4], 11)) { > - msg = pkcs7_parse_message(buf, buflen); > - if (IS_ERR(msg)) > - return NULL; > - return msg; > - } > - > - /* > - * Otherwise, we should add a dummy prefix sequence for pkcs7 > - * message parser to be able to process. > - * NOTE: EDK2 also uses similar hack in WrapPkcs7Data() > - * in CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyCommon.c > - * TODO: > - * The header should be composed in a more refined manner. > - */ > - EFI_PRINT("Makeshift prefix added to authentication data\n"); > - ebuflen = sizeof(pkcs7_hdr) + buflen; > - if (ebuflen <= 0x7f) { > - EFI_PRINT("Data is too short\n"); > - return NULL; > - } > - > - ebuf = malloc(ebuflen); > - if (!ebuf) { > - EFI_PRINT("Out of memory\n"); > - return NULL; > - } > - > - memcpy(ebuf, pkcs7_hdr, sizeof(pkcs7_hdr)); > - memcpy(ebuf + sizeof(pkcs7_hdr), buf, buflen); > - len = ebuflen - 4; > - ebuf[2] = (len >> 8) & 0xff; > - ebuf[3] = len & 0xff; > - len = ebuflen - 0x13; > - ebuf[0x11] = (len >> 8) & 0xff; > - ebuf[0x12] = len & 0xff; > - > - msg = pkcs7_parse_message(ebuf, ebuflen); > - > - if (IS_ERR(msg)) { > - free(ebuf); > - return NULL; > - } > - > - *tmpbuf = ebuf; > - return msg; > -} > > /** > * efi_variable_authenticate - authenticate a variable > @@ -215,10 +130,10 @@ static efi_status_t efi_variable_authenticate(u16 *variable, > goto err; > > /* ebuf should be kept valid during the authentication */ > - var_sig = efi_variable_parse_signature(auth->auth_info.cert_data, > - auth->auth_info.hdr.dwLength > - - sizeof(auth->auth_info), > - &ebuf); > + var_sig = efi_parse_pkcs7_header(auth->auth_info.cert_data, > + auth->auth_info.hdr.dwLength > + - sizeof(auth->auth_info), > + &ebuf); > if (!var_sig) { > EFI_PRINT("Parsing variable's signature failed\n"); > goto err; >
diff --git a/include/efi_loader.h b/include/efi_loader.h index 76cd2b36f2..b9226208f5 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -810,6 +810,10 @@ bool efi_secure_boot_enabled(void); bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp, WIN_CERTIFICATE **auth, size_t *auth_len); +struct pkcs7_message *efi_parse_pkcs7_header(const void *buf, + size_t buflen, + u8 **tmpbuf); + /* runtime implementation of memcpy() */ void efi_memcpy_runtime(void *dest, const void *src, size_t n); diff --git a/lib/efi_loader/efi_signature.c b/lib/efi_loader/efi_signature.c index 79dee27421..9ab071b611 100644 --- a/lib/efi_loader/efi_signature.c +++ b/lib/efi_loader/efi_signature.c @@ -27,6 +27,91 @@ const efi_guid_t efi_guid_cert_x509_sha256 = EFI_CERT_X509_SHA256_GUID; const efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID; #ifdef CONFIG_EFI_SECURE_BOOT +static u8 pkcs7_hdr[] = { + /* SEQUENCE */ + 0x30, 0x82, 0x05, 0xc7, + /* OID: pkcs7-signedData */ + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, + /* Context Structured? */ + 0xa0, 0x82, 0x05, 0xb8, +}; + +/** + * efi_parse_pkcs7_header - parse a signature in payload + * @buf: Pointer to payload's value + * @buflen: Length of @buf + * @tmpbuf: Pointer to temporary buffer + * + * Parse a signature embedded in payload's value and instantiate + * a pkcs7_message structure. Since pkcs7_parse_message() accepts only + * pkcs7's signedData, some header needed be prepended for correctly + * parsing authentication data + * A temporary buffer will be allocated if needed, and it should be + * kept valid during the authentication because some data in the buffer + * will be referenced by efi_signature_verify(). + * + * Return: Pointer to pkcs7_message structure on success, NULL on error + */ +struct pkcs7_message *efi_parse_pkcs7_header(const void *buf, + size_t buflen, + u8 **tmpbuf) +{ + u8 *ebuf; + size_t ebuflen, len; + struct pkcs7_message *msg; + + /* + * This is the best assumption to check if the binary is + * already in a form of pkcs7's signedData. + */ + if (buflen > sizeof(pkcs7_hdr) && + !memcmp(&((u8 *)buf)[4], &pkcs7_hdr[4], 11)) { + msg = pkcs7_parse_message(buf, buflen); + if (IS_ERR(msg)) + return NULL; + return msg; + } + + /* + * Otherwise, we should add a dummy prefix sequence for pkcs7 + * message parser to be able to process. + * NOTE: EDK2 also uses similar hack in WrapPkcs7Data() + * in CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyCommon.c + * TODO: + * The header should be composed in a more refined manner. + */ + EFI_PRINT("Makeshift prefix added to authentication data\n"); + ebuflen = sizeof(pkcs7_hdr) + buflen; + if (ebuflen <= 0x7f) { + EFI_PRINT("Data is too short\n"); + return NULL; + } + + ebuf = malloc(ebuflen); + if (!ebuf) { + EFI_PRINT("Out of memory\n"); + return NULL; + } + + memcpy(ebuf, pkcs7_hdr, sizeof(pkcs7_hdr)); + memcpy(ebuf + sizeof(pkcs7_hdr), buf, buflen); + len = ebuflen - 4; + ebuf[2] = (len >> 8) & 0xff; + ebuf[3] = len & 0xff; + len = ebuflen - 0x13; + ebuf[0x11] = (len >> 8) & 0xff; + ebuf[0x12] = len & 0xff; + + msg = pkcs7_parse_message(ebuf, ebuflen); + + if (IS_ERR(msg)) { + free(ebuf); + return NULL; + } + + *tmpbuf = ebuf; + return msg; +} /** * efi_hash_regions - calculate a hash value diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index 0c689cfb47..ba0874e9e7 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -24,91 +24,6 @@ #include <asm/sections.h> #ifdef CONFIG_EFI_SECURE_BOOT -static u8 pkcs7_hdr[] = { - /* SEQUENCE */ - 0x30, 0x82, 0x05, 0xc7, - /* OID: pkcs7-signedData */ - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, - /* Context Structured? */ - 0xa0, 0x82, 0x05, 0xb8, -}; - -/** - * efi_variable_parse_signature - parse a signature in variable - * @buf: Pointer to variable's value - * @buflen: Length of @buf - * @tmpbuf: Pointer to temporary buffer - * - * Parse a signature embedded in variable's value and instantiate - * a pkcs7_message structure. Since pkcs7_parse_message() accepts only - * pkcs7's signedData, some header needed be prepended for correctly - * parsing authentication data, particularly for variable's. - * A temporary buffer will be allocated if needed, and it should be - * kept valid during the authentication because some data in the buffer - * will be referenced by efi_signature_verify(). - * - * Return: Pointer to pkcs7_message structure on success, NULL on error - */ -static struct pkcs7_message *efi_variable_parse_signature(const void *buf, - size_t buflen, - u8 **tmpbuf) -{ - u8 *ebuf; - size_t ebuflen, len; - struct pkcs7_message *msg; - - /* - * This is the best assumption to check if the binary is - * already in a form of pkcs7's signedData. - */ - if (buflen > sizeof(pkcs7_hdr) && - !memcmp(&((u8 *)buf)[4], &pkcs7_hdr[4], 11)) { - msg = pkcs7_parse_message(buf, buflen); - if (IS_ERR(msg)) - return NULL; - return msg; - } - - /* - * Otherwise, we should add a dummy prefix sequence for pkcs7 - * message parser to be able to process. - * NOTE: EDK2 also uses similar hack in WrapPkcs7Data() - * in CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyCommon.c - * TODO: - * The header should be composed in a more refined manner. - */ - EFI_PRINT("Makeshift prefix added to authentication data\n"); - ebuflen = sizeof(pkcs7_hdr) + buflen; - if (ebuflen <= 0x7f) { - EFI_PRINT("Data is too short\n"); - return NULL; - } - - ebuf = malloc(ebuflen); - if (!ebuf) { - EFI_PRINT("Out of memory\n"); - return NULL; - } - - memcpy(ebuf, pkcs7_hdr, sizeof(pkcs7_hdr)); - memcpy(ebuf + sizeof(pkcs7_hdr), buf, buflen); - len = ebuflen - 4; - ebuf[2] = (len >> 8) & 0xff; - ebuf[3] = len & 0xff; - len = ebuflen - 0x13; - ebuf[0x11] = (len >> 8) & 0xff; - ebuf[0x12] = len & 0xff; - - msg = pkcs7_parse_message(ebuf, ebuflen); - - if (IS_ERR(msg)) { - free(ebuf); - return NULL; - } - - *tmpbuf = ebuf; - return msg; -} /** * efi_variable_authenticate - authenticate a variable @@ -215,10 +130,10 @@ static efi_status_t efi_variable_authenticate(u16 *variable, goto err; /* ebuf should be kept valid during the authentication */ - var_sig = efi_variable_parse_signature(auth->auth_info.cert_data, - auth->auth_info.hdr.dwLength - - sizeof(auth->auth_info), - &ebuf); + var_sig = efi_parse_pkcs7_header(auth->auth_info.cert_data, + auth->auth_info.hdr.dwLength + - sizeof(auth->auth_info), + &ebuf); if (!var_sig) { EFI_PRINT("Parsing variable's signature failed\n"); goto err;
The pkcs7 header parsing functionality is pretty generic, and can be used by other features like capsule authentication. Make the function an extern, also changing it's name to efi_parse_pkcs7_header Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org> --- include/efi_loader.h | 4 ++ lib/efi_loader/efi_signature.c | 85 +++++++++++++++++++++++++++++++ lib/efi_loader/efi_variable.c | 93 ++-------------------------------- 3 files changed, 93 insertions(+), 89 deletions(-) -- 2.17.1