CMS Verification Fails with SE050-Stored Key Unless -no_attr_verify: Is This Expected?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

CMS Verification Fails with SE050-Stored Key Unless -no_attr_verify: Is This Expected?

Jump to solution
4,157 Views
norisan
Contributor II

Hi, all.

Using Rust and FFI with OpenSSL library functions, I performed a CMS signature using the key (and certificate) stored in SE050 (in detached format for now).
However, when I attempted verification, it failed.
Suspecting a program bug, I tried verifying using the OpenSSL command-line tool.

The results are as follows.
# openssl cms -verify -in signed.data -inform DER -content content.data -binary -CAfile ../ca.pem -out /dev/null
CMS Verification failure
20A0A39CFFFF0000:error:1700009E:CMS routines:CMS_SignerInfo_verify:verification failure:/usr/src/debug/openssl/3.3.1/crypto/cms/cms_sd.c:958:

Based on the error message, adding the -no_attr_verify flag successfully passed the verification.
# openssl cms -verify -in signed.data -inform DER -content content.data -binary -CAfile ../ca.pem -out /dev/null -no_attr_verify
CMS Verification successful

Now, here's my question:
 Is this the correct behavior?
 Is it fundamentally wrong to attempt to generate a CMS using keys stored in the HSM?
 We're planning to implement the attachment format next. Are there any issues with that?

I apologize for my poor writing, but I appreciate your understanding.

best reguards.

Tags (4)
0 Kudos
Reply
1 Solution
3,223 Views
norisan
Contributor II

Hi, @carlos_o and everyone!

> CMS is not listed to be supported with the Plug and Trust MW.
I was pretty disappointed with the above, but after some trial and error, it worked out, so I'm reporting back.

After creating a config file with the following content, exporting it as the environment variable OPENSSL_CONF, and then running the program, I successfully generated signed data that passed verification, including signedAttrs verification.

openssl_conf = openssl_init

[openssl_init]
providers = provider_sect

[provider_sect]
default = default_sect
base    = base_sect
pkcs11  = pkcs11_sect

[default_sect]
activate = 1

[base_sect]
activate = 1

[pkcs11_sect]
pkcs11-module-path = /path/to/libsss_pkcs11.so => Set the actual path
activate           = 1

There are several parts I don't fully understand, but I'm reporting that it worked for now.

If you know the reason, I'd appreciate an explanation.

I hope this helps someone else too.

That's all for now.

View solution in original post

8 Replies
4,135 Views
norisan
Contributor II
Additional information:
The key pair is obtained using the OpenSSL provider (sssProvider), while the certificate utilizes the cryptoki crate + libsss_pkcs11.so.
The key (and certificate) uses ECDSA with a 384-bit key.
0 Kudos
Reply
4,061 Views
carlos_o
NXP TechSupport
NXP TechSupport

Hi @norisan 

Apologies the late reply 

Could you please provide more details about your sign process?

How are you using the provider to sign the data?

 

0 Kudos
Reply
4,042 Views
norisan
Contributor II

Hi @carlos_o 

Thank you for your reply.
The general flow is as follows.
* The programming language is Rust.
   Error handling and other details have been omitted.


    // load providers
    let def_pv = CString::new("default")?;
    SSL_PROVIDER_load(ptr::null_mut(), def_pv.as_ptr());
    let sss_pv = CString::new("sssProvider")?;
    SSL_PROVIDER_load(ptr::null_mut(), sss_pv.as_ptr());

    // uri for get private key from SE050
    let uri = CString::new("nxp:0xXXXXXXXX".to_string())?;

    // get store
    let store = OSSL_STORE_open(
        c_uri.as_ptr(),
        std::ptr::null(),
        std::ptr::null_mut(),
        None,
        std::ptr::null_mut(),
    );

    // got a pkey
    let mut pkey: *mut openssl_bindings::EVP_PKEY = ptr::null_mut();
    loop {
        let info = openssl_bindings::OSSL_STORE_load(store);
        let info_type = openssl_bindings::OSSL_STORE_INFO_get_type(info);
            let got = openssl_bindings::OSSL_STORE_INFO_get1_PKEY(info);
            pkey = got;
            break;
        }
    }

    // Generate PKey<Private> from EVP_PKEY*
    let pkey_ptr: *mut openssl_sys::EVP_PKEY = pkey as *mut openssl_sys::EVP_PKEY;
    let private_key = PKey::from_ptr(pkey_ptr);

    // The end entity is obtained via PKCS#11 (cryptoki crate + libsss_pkcs11.so).
    // [0]: End Entity [1]: Intermediate CA [2]: Root CA
    let certs = ...;

    let client_cert = certs[0];

    // Generate a CA chain from certificates
    let cert_chain = ...;

    let flags = CMS_BINARY | CMS_STREAM | CMS_DETACHED;

    // Generate CMS
    let cms = CMS_sign(
        ptr::null_mut(),
        ptr::null_mut(),
        cert_chain,
        ptr::null_mut(),
        flags | CMS_PARTIAL,
    );

    // Add SignerInfo
    let signer = CMS_add1_signer(
        cms,
        client_cert,
        private_key,
        EVP_sha384(),
        0,
    );

    // Implement the signature
    // input_bio is generated from the file to be signed
    CMS_final(cms, input_bio, ptr::null_mut(), flags);

    // Output CMS signed data
    ....

 
Signature data generated using SoftHSM2 or a file (PKCS#12 file) for key and certificate acquisition can be successfully verified without adding the ‘-no_attr_verify’ option to the openssl command.

Are there any additional steps required when using data obtained from SE050?

Thanks.

0 Kudos
Reply
3,862 Views
carlos_o
NXP TechSupport
NXP TechSupport

Hi @norisan ,

When you try to verify the signature with openssl you are not using the provider to the SE05.

openssl in command line need the "--provider" option to use it.

Please reveiw the example scripts at \SE-PLUG-TRUST-MW_04.07.01\simw-top\sss\plugin\openssl_provider\scripts

The supported programming languages are listed in the prerequisites of each development environment given at the Plug & Trust Middleware documentation.

 

0 Kudos
Reply
3,807 Views
norisan
Contributor II

Hi @carlos_o,

Thanks for your reply.
Are you saying to add the “-provider” option when verifying with the openssl command?

# EX_SSS_BOOT_SSS_PORT=/dev/i2c-4:0x48 \
    openssl cms -verify \
    --provider default \
    --provider sssProvider \
    -propquery "?nxp_prov.signature.ecdsa=yes,?nxp_prov.keymgmt.ec=yes" \
    -signer nxp:0xXXXXXXXX \
    -in sign.data \
    -inform DER \
    -content content.data \
    -binary \
    -CAfile ca.pem \
    -out /dev/null
App   :INFO :Using PortName='/dev/i2c-4:0x48' (ENV: EX_SSS_BOOT_SSS_PORT=/dev/i2c-4:0x48)
sss   :INFO :atr (Len=35)
      01 A0 00 00    03 96 04 03    E8 00 FE 02    0B 03 E8 00
      01 00 00 00    00 64 13 88    0A 00 65 53    45 30 35 31
      00 00 00
sss   :WARN :Communication channel is Plain.
sss   :WARN :!!!Not recommended for production use.!!!
CMS Verification failure
20606D8BFFFF0000:error:1700009E:CMS routines:CMS_SignerInfo_verify:verification failure:/usr/src/debug/openssl/3.3.1/crypto/cms/cms_sd.c:958:

 

“-signer” specifies the ID of the certificate object.
However, the error remains the same(Is my approach wrong?).

The only example provided in the directory you mentioned is for “pkeyutl” (openssl_EccSign.py). Since it is unsuitable for signing and verification using CMS_sign() and CMS_verify(), is that why no examples exist for those functions?

0 Kudos
Reply
3,734 Views
carlos_o
NXP TechSupport
NXP TechSupport

Hi @norisan 

The "--provider" option is to make sure that you are using the provider to the S05 to do the verify. When the verify fails without "-no_attr_verify" means that the signed attributes don't match. CMS is not listed to be supported with the Plug and Trust MW.

0 Kudos
Reply
3,224 Views
norisan
Contributor II

Hi, @carlos_o and everyone!

> CMS is not listed to be supported with the Plug and Trust MW.
I was pretty disappointed with the above, but after some trial and error, it worked out, so I'm reporting back.

After creating a config file with the following content, exporting it as the environment variable OPENSSL_CONF, and then running the program, I successfully generated signed data that passed verification, including signedAttrs verification.

openssl_conf = openssl_init

[openssl_init]
providers = provider_sect

[provider_sect]
default = default_sect
base    = base_sect
pkcs11  = pkcs11_sect

[default_sect]
activate = 1

[base_sect]
activate = 1

[pkcs11_sect]
pkcs11-module-path = /path/to/libsss_pkcs11.so => Set the actual path
activate           = 1

There are several parts I don't fully understand, but I'm reporting that it worked for now.

If you know the reason, I'd appreciate an explanation.

I hope this helps someone else too.

That's all for now.

3,197 Views
carlos_o
NXP TechSupport
NXP TechSupport

Hi @norisan 

Thanks for sharing the workaround you found. 

0 Kudos
Reply