Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add functionality for external signatures #2

Merged
merged 3 commits into from
Jan 27, 2021

Conversation

nick-child-ibm
Copy link
Collaborator

@nick-child-ibm nick-child-ibm commented Jan 26, 2021

This PR includes the implementation, documentation, and the testing for secvarctl ability to accept externally signed data. Rather than only supporting signatures computed internally. This will let secvarctl produce the presigned digest, allowing the user to use an external signing framework for the actual signature generation. From there, secvarctl can use this raw signed data when generating an auth or PKCS7 file. The process will look like this:
$ secvarctl generate c:x -n <varName> -t <timestamp> -i <newCrt> -o <digest.bin>
$<user generates the signature using another tool, resulting in file <signature.bin>
$secvarctl generate c:a -n <varName> -t <timestamp> -i <newCrt> -o <update.auth> -s <signature.bin> -c <signingCrt.pem>
NOTE: The timestamp and varName must be the exact same for both secvarctl commands

@@ -816,7 +817,7 @@ int to_pkcs7_already_signed_data(unsigned char **pkcs7, size_t *pkcs7Size, const
if (sigs[i]) free(sigs[i]);
}
if (sigs) free (sigs);

if (sig_sizes) free(sig_sizes);
Copy link
Collaborator

@erichte-ibm erichte-ibm Jan 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these fixes to a bug/leak introduced in the first commit of this PR? If so you can just squash this commit into that one, no need to have a separate commit for it.

If this is fixing an unrelated bug, then nevermind.

@@ -49,13 +49,14 @@ extern int verbose;
typedef struct PKCS7Info {
unsigned char **crts; // signing crt DER
size_t *crtSizes;
unsigned char **keys; // signing key DER
unsigned char **keys; // signing key DER or signatures (depends on alreadySignedFlag)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, I'm not fully up on the pkcs7 implementation for mbedtls, but make sure if you are adding features to the pkcs7 generation code for new features in secvarctl, that those changes make sense for mbedtls as well.

It may be suggested that rolling pre-signed data into a pkcs7 blob should be handled in glue code outside of the library (i.e. in secvarctl) instead of in the library itself. Not suggest you change this now, but more of a warning. Maybe look at other implementations of similar algos/specs/etc and see if there's precedence for this?

@erichte-ibm
Copy link
Collaborator

Looks good to me, I'm marking as approved, but will wait for an answer on the squash commit question before merging.

…vate key

Previously, if a user wanted to make a signed auth file, they would need to supply secvarctl with public and private key pairs for signing the data. Recently, it has come to our attention that some users will not have access to their private keys as it may be under the guard of a signing framework server. In this case, the most secvarctl can do is to generate the hash to be signed. From their, it is up to the user to generate the signature with their signing framework. Then the user can give secvarctl the signature and the generation of PKCS7/auth files can resume. It is important the user uses the same timestamp in both the presignature generation and auth/PKCS7 generation. Now, with this commit, the user can use a signing framework to generate an auth file using the below commands:
    - $ secvarctl generate c:x -n <varName> -t <timeStamp> -i <certificate> -o <sha256.hash>
    - $ <user sends hash to be signed -in <sha256.hash> -out <signature.bin>
    - $ secvarctl generate c:a -n <varName> <timeStamp> -i <certificate> -o <newAuth> -c <signingCert> -s <signature.bin>
In the previous commit, abilities to create auth and PKCS7 files with a raw signed data files in replacement of private key arguments was introduced. This commit adds those changes to the documentation and help messages
In the two previus commits, documentation and functionality were added to allow for secvarctl to accept an external signature rather than generating the signature internally. Now, we add tests to ensure that the enhanement was executed appropriately. To test we generate a signed auth file to work as our control. Then we generate an unsigned hash digest and sign it externally with openssl. We then use the signature to generate another signed auth file that will be our experiment. If the control and experiment contain the exact same data then the test passes.
@nick-child-ibm nick-child-ibm merged commit 7d818cf into open-power:main Jan 27, 2021
nick-child-ibm added a commit to nick-child-ibm/secvarctl that referenced this pull request Oct 5, 2023
There are several things wrong with get_hash_data:
	1. it doesn't work, all returned hashes are all 0x00
	2. memory leak of hash allocated by crypto_md_generate_hash
	3. memory leak of der data buffer from is_x509certificate
	4. useless casting of hash_ids to x509_hash_ids

Issues 1-3 can be seen below
$ bin/secvarctl-dbg -m guest generate f:e -i ./test/testdata/guest/x509certs/dbx.crt -o dbx.esl -n dbx
  error: invalid crypto alg key 8
  error: invalid crypto alg key 11
  error: invalid crypto alg key 8
  RESULT: SUCCESS

  =================================================================
  ==88342==ERROR: LeakSanitizer: detected memory leaks

  Direct leak of 813 byte(s) in 1 object(s) allocated from:
    #0 0x7fa153bdebb8 in __interceptor_malloc (/lib64/libasan.so.5+0xefbb8)
    #1 0x7fa1537a42da in PEM_read_bio_ex (/lib64/libcrypto.so.1.1+0x19f2da)

  Direct leak of 32 byte(s) in 1 object(s) allocated from:
    #0 0x7fa153bdebb8 in __interceptor_malloc (/lib64/libasan.so.5+0xefbb8)
    #1 0x463e27 in crypto_md_generate_hash src/crypto_openssl.c:768
    open-power#2 0x445b4a in get_hash_data backends/guest/common/generate.c:477
    open-power#3 0x43234a in generate_esl backends/guest/guest_svc_generate.c:73
    open-power#4 0x43505e in generate_data backends/guest/guest_svc_generate.c:365
    open-power#5 0x439382 in guest_generate_command backends/guest/guest_svc_generate.c:690
    open-power#6 0x4069b4 in main /home/nchild/IBM/secvarctl-stuff/erichte-guest-devel/secvarctl/secvarctl.c:249
    open-power#7 0x7fa152558d84 in __libc_start_main (/lib64/libc.so.6+0x3ad84)

  SUMMARY: AddressSanitizer: 845 byte(s) leaked in 2 allocation(s).

$ hexdump dbx.esl
  0000000 1626 c1c4 504c 4092 a9ac f941 9336 2843
  0000010 004c 0000 0000 0000 0030 0000 0000 0000
  0000020 0000 0000 0000 0000 0000 0000 0000 0000
  *
  0000040 0000 0000 0000 0000 0000 0000
  000004c

Fixing issue 1 and 2:
  get_hash_data() acts as a middle function during hash generation.
  First generate_esl() allocates an empty hash buffer and hands it to
  get_hash_data(). get_hash_data() then hands the address to that buffer
  to crypto_md_generate_hash(). crypto_md_generate_hash() allocates its
  own buffer and overwrites our pointer to our buffer. get_hash_data()
  has no way of updating generate_esl() of the new address. This results
  in a successful hash generation but a memoryleaks and an empty hash
  in the esl:
  To avoid this, simply copy the returned buffer into the existing buffer.

Fixing issue 3:
  is_x509certificate will allocate and return data if it finds the given
  buffer contains an x509.
  To fix this, simply free the der data after generating the hash.

Fixing issue 4:
  This is only a semi-issue, but previously, if the buffer was a
  certificate then we would cast our hash_function parameter into an
  x509 hash function ID. Later on this value get passed to
  get_crypto_alg_id() to get the crypto library specific MD identifier.
  get_crypto_alg_id() does not keep track of x509 hash function ID (and
  tbh the difference between them is not clear) and defaults to sha256.
  The point of converting the given hash id to x509 hash id only to then
  convert that value into crypto library specific ID is unnecessary.
  To fix just stick with the hash function passed to the function.

Lastly, add a test case for all this.

Signed-off-by: Nick Child <nick.child@ibm.com>
nick-child-ibm added a commit to nick-child-ibm/secvarctl that referenced this pull request Oct 6, 2023
There are several things wrong with get_hash_data:
	1. it doesn't work, all returned hashes are all 0x00
	2. memory leak of hash allocated by crypto_md_generate_hash
	3. memory leak of der data buffer from is_x509certificate
	4. useless casting of hash_ids to x509_hash_ids

Issues 1-3 can be seen below
$ bin/secvarctl-dbg -m guest generate f:e -i ./test/testdata/guest/x509certs/dbx.crt -o dbx.esl -n dbx
  error: invalid crypto alg key 8
  error: invalid crypto alg key 11
  error: invalid crypto alg key 8
  RESULT: SUCCESS

  =================================================================
  ==88342==ERROR: LeakSanitizer: detected memory leaks

  Direct leak of 813 byte(s) in 1 object(s) allocated from:
    #0 0x7fa153bdebb8 in __interceptor_malloc (/lib64/libasan.so.5+0xefbb8)
    #1 0x7fa1537a42da in PEM_read_bio_ex (/lib64/libcrypto.so.1.1+0x19f2da)

  Direct leak of 32 byte(s) in 1 object(s) allocated from:
    #0 0x7fa153bdebb8 in __interceptor_malloc (/lib64/libasan.so.5+0xefbb8)
    #1 0x463e27 in crypto_md_generate_hash src/crypto_openssl.c:768
    open-power#2 0x445b4a in get_hash_data backends/guest/common/generate.c:477
    open-power#3 0x43234a in generate_esl backends/guest/guest_svc_generate.c:73
    open-power#4 0x43505e in generate_data backends/guest/guest_svc_generate.c:365
    open-power#5 0x439382 in guest_generate_command backends/guest/guest_svc_generate.c:690
    open-power#6 0x4069b4 in main /home/nchild/IBM/secvarctl-stuff/erichte-guest-devel/secvarctl/secvarctl.c:249
    open-power#7 0x7fa152558d84 in __libc_start_main (/lib64/libc.so.6+0x3ad84)

  SUMMARY: AddressSanitizer: 845 byte(s) leaked in 2 allocation(s).

$ hexdump dbx.esl
  0000000 1626 c1c4 504c 4092 a9ac f941 9336 2843
  0000010 004c 0000 0000 0000 0030 0000 0000 0000
  0000020 0000 0000 0000 0000 0000 0000 0000 0000
  *
  0000040 0000 0000 0000 0000 0000 0000
  000004c

Fixing issue 1 and 2:
  get_hash_data() acts as a middle function during hash generation.
  First generate_esl() allocates an empty hash buffer and hands it to
  get_hash_data(). get_hash_data() then hands the address to that buffer
  to crypto_md_generate_hash(). crypto_md_generate_hash() allocates its
  own buffer and overwrites our pointer to our buffer. get_hash_data()
  has no way of updating generate_esl() of the new address. This results
  in a successful hash generation but a memoryleaks and an empty hash
  in the esl:
  To avoid this, simply copy the returned buffer into the existing buffer.

Fixing issue 3:
  is_x509certificate will allocate and return data if it finds the given
  buffer contains an x509.
  To fix this, simply free the der data after generating the hash.

Fixing issue 4:
  This is only a semi-issue, but previously, if the buffer was a
  certificate then we would cast our hash_function parameter into an
  x509 hash function ID. Later on this value get passed to
  get_crypto_alg_id() to get the crypto library specific MD identifier.
  get_crypto_alg_id() does not keep track of x509 hash function ID (and
  tbh the difference between them is not clear) and defaults to sha256.
  The point of converting the given hash id to x509 hash id only to then
  convert that value into crypto library specific ID is unnecessary.
  To fix just stick with the hash function passed to the function.

Lastly, add a test case for all this.

Signed-off-by: Nick Child <nick.child@ibm.com>
erichte-ibm pushed a commit that referenced this pull request Oct 6, 2023
There are several things wrong with get_hash_data:
	1. it doesn't work, all returned hashes are all 0x00
	2. memory leak of hash allocated by crypto_md_generate_hash
	3. memory leak of der data buffer from is_x509certificate
	4. useless casting of hash_ids to x509_hash_ids

Issues 1-3 can be seen below
$ bin/secvarctl-dbg -m guest generate f:e -i ./test/testdata/guest/x509certs/dbx.crt -o dbx.esl -n dbx
  error: invalid crypto alg key 8
  error: invalid crypto alg key 11
  error: invalid crypto alg key 8
  RESULT: SUCCESS

  =================================================================
  ==88342==ERROR: LeakSanitizer: detected memory leaks

  Direct leak of 813 byte(s) in 1 object(s) allocated from:
    #0 0x7fa153bdebb8 in __interceptor_malloc (/lib64/libasan.so.5+0xefbb8)
    #1 0x7fa1537a42da in PEM_read_bio_ex (/lib64/libcrypto.so.1.1+0x19f2da)

  Direct leak of 32 byte(s) in 1 object(s) allocated from:
    #0 0x7fa153bdebb8 in __interceptor_malloc (/lib64/libasan.so.5+0xefbb8)
    #1 0x463e27 in crypto_md_generate_hash src/crypto_openssl.c:768
    #2 0x445b4a in get_hash_data backends/guest/common/generate.c:477
    #3 0x43234a in generate_esl backends/guest/guest_svc_generate.c:73
    #4 0x43505e in generate_data backends/guest/guest_svc_generate.c:365
    #5 0x439382 in guest_generate_command backends/guest/guest_svc_generate.c:690
    #6 0x4069b4 in main /home/nchild/IBM/secvarctl-stuff/erichte-guest-devel/secvarctl/secvarctl.c:249
    #7 0x7fa152558d84 in __libc_start_main (/lib64/libc.so.6+0x3ad84)

  SUMMARY: AddressSanitizer: 845 byte(s) leaked in 2 allocation(s).

$ hexdump dbx.esl
  0000000 1626 c1c4 504c 4092 a9ac f941 9336 2843
  0000010 004c 0000 0000 0000 0030 0000 0000 0000
  0000020 0000 0000 0000 0000 0000 0000 0000 0000
  *
  0000040 0000 0000 0000 0000 0000 0000
  000004c

Fixing issue 1 and 2:
  get_hash_data() acts as a middle function during hash generation.
  First generate_esl() allocates an empty hash buffer and hands it to
  get_hash_data(). get_hash_data() then hands the address to that buffer
  to crypto_md_generate_hash(). crypto_md_generate_hash() allocates its
  own buffer and overwrites our pointer to our buffer. get_hash_data()
  has no way of updating generate_esl() of the new address. This results
  in a successful hash generation but a memoryleaks and an empty hash
  in the esl:
  To avoid this, simply copy the returned buffer into the existing buffer.

Fixing issue 3:
  is_x509certificate will allocate and return data if it finds the given
  buffer contains an x509.
  To fix this, simply free the der data after generating the hash.

Fixing issue 4:
  This is only a semi-issue, but previously, if the buffer was a
  certificate then we would cast our hash_function parameter into an
  x509 hash function ID. Later on this value get passed to
  get_crypto_alg_id() to get the crypto library specific MD identifier.
  get_crypto_alg_id() does not keep track of x509 hash function ID (and
  tbh the difference between them is not clear) and defaults to sha256.
  The point of converting the given hash id to x509 hash id only to then
  convert that value into crypto library specific ID is unnecessary.
  To fix just stick with the hash function passed to the function.

Lastly, add a test case for all this.

Signed-off-by: Nick Child <nick.child@ibm.com>
nick-child-ibm added a commit that referenced this pull request Feb 6, 2024
There are several things wrong with get_hash_data:
	1. it doesn't work, all returned hashes are all 0x00
	2. memory leak of hash allocated by crypto_md_generate_hash
	3. memory leak of der data buffer from is_x509certificate
	4. useless casting of hash_ids to x509_hash_ids

Issues 1-3 can be seen below
$ bin/secvarctl-dbg -m guest generate f:e -i ./test/testdata/guest/x509certs/dbx.crt -o dbx.esl -n dbx
  error: invalid crypto alg key 8
  error: invalid crypto alg key 11
  error: invalid crypto alg key 8
  RESULT: SUCCESS

  =================================================================
  ==88342==ERROR: LeakSanitizer: detected memory leaks

  Direct leak of 813 byte(s) in 1 object(s) allocated from:
    #0 0x7fa153bdebb8 in __interceptor_malloc (/lib64/libasan.so.5+0xefbb8)
    #1 0x7fa1537a42da in PEM_read_bio_ex (/lib64/libcrypto.so.1.1+0x19f2da)

  Direct leak of 32 byte(s) in 1 object(s) allocated from:
    #0 0x7fa153bdebb8 in __interceptor_malloc (/lib64/libasan.so.5+0xefbb8)
    #1 0x463e27 in crypto_md_generate_hash src/crypto_openssl.c:768
    #2 0x445b4a in get_hash_data backends/guest/common/generate.c:477
    #3 0x43234a in generate_esl backends/guest/guest_svc_generate.c:73
    #4 0x43505e in generate_data backends/guest/guest_svc_generate.c:365
    #5 0x439382 in guest_generate_command backends/guest/guest_svc_generate.c:690
    #6 0x4069b4 in main /home/nchild/IBM/secvarctl-stuff/erichte-guest-devel/secvarctl/secvarctl.c:249
    #7 0x7fa152558d84 in __libc_start_main (/lib64/libc.so.6+0x3ad84)

  SUMMARY: AddressSanitizer: 845 byte(s) leaked in 2 allocation(s).

$ hexdump dbx.esl
  0000000 1626 c1c4 504c 4092 a9ac f941 9336 2843
  0000010 004c 0000 0000 0000 0030 0000 0000 0000
  0000020 0000 0000 0000 0000 0000 0000 0000 0000
  *
  0000040 0000 0000 0000 0000 0000 0000
  000004c

Fixing issue 1 and 2:
  get_hash_data() acts as a middle function during hash generation.
  First generate_esl() allocates an empty hash buffer and hands it to
  get_hash_data(). get_hash_data() then hands the address to that buffer
  to crypto_md_generate_hash(). crypto_md_generate_hash() allocates its
  own buffer and overwrites our pointer to our buffer. get_hash_data()
  has no way of updating generate_esl() of the new address. This results
  in a successful hash generation but a memoryleaks and an empty hash
  in the esl:
  To avoid this, simply copy the returned buffer into the existing buffer.

Fixing issue 3:
  is_x509certificate will allocate and return data if it finds the given
  buffer contains an x509.
  To fix this, simply free the der data after generating the hash.

Fixing issue 4:
  This is only a semi-issue, but previously, if the buffer was a
  certificate then we would cast our hash_function parameter into an
  x509 hash function ID. Later on this value get passed to
  get_crypto_alg_id() to get the crypto library specific MD identifier.
  get_crypto_alg_id() does not keep track of x509 hash function ID (and
  tbh the difference between them is not clear) and defaults to sha256.
  The point of converting the given hash id to x509 hash id only to then
  convert that value into crypto library specific ID is unnecessary.
  To fix just stick with the hash function passed to the function.

Lastly, add a test case for all this.

Signed-off-by: Nick Child <nick.child@ibm.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants