Re: Updating RSA public key generation and signature verification from 1.1.1 to 3.0

2022-10-01 Thread Tomas Mraz
I am glad to hear that.

Regards,
Tomas Mraz, OpenSSL

On Fri, 2022-09-30 at 17:18 +, GonzalezVillalobos, Diego wrote:
> [AMD Official Use Only - General]
> 
> Hello Tomas,
> 
> There was a logic error in my code, I did not realize that the first
> iteration of the verification was supposed to fail. The verification
> is working correctly! I apologize for my last response. I really
> appreciate all your help!
> 
> Thank you very much,
> 
> Diego Gonzalez
> -
> -
>  
> 
> -Original Message-
> From: Tomas Mraz  
> Sent: Friday, September 30, 2022 1:22 AM
> To: GonzalezVillalobos, Diego ;
> openssl-users@openssl.org
> Subject: Re: Updating RSA public key generation and signature
> verification from 1.1.1 to 3.0
> 
> Caution: This message originated from an External Source. Use proper
> caution when opening attachments, clicking links, or responding.
> 
> 
> Hi,
> 
> unfortunately I do not see anything wrong with the code. Does the
> EVP_DigestVerifyFinal return 0 or negative value? I do not think this
> is a bug in OpenSSL as this API is thoroughly tested and it is highly
> improbable that there would be a bug in the ECDSA verification
> through this API.
> 
> I am currently out of ideas on what could be wrong or how to
> investigate further. Perhaps someone else can chime in on what can be
> wrong?
> 
> Tomas
> 
> On Thu, 2022-09-29 at 19:22 +, GonzalezVillalobos, Diego wrote:
> > [AMD Official Use Only - General]
> > 
> > Hello Tomas,
> > 
> > So, I made sure that px_size and py_size are equal to the group
> > order 
> > (48). I was able to verify successfully using our previous method
> > (deprecated) with the new key generation method, but I'm still not 
> > able to get the digestverify to work successfully. As a reminder
> > this 
> > is how we were verifying before:
> > 
> > // Determine if SHA_TYPE is 256 bit or 384 bit if 
> > (parent_cert->pub_key_algo == SEV_SIG_ALGO_RSA_SHA256 || 
> > parent_cert->pub_key_algo == SEV_SIG_ALGO_ECDSA_SHA256
> > ||parent_cert-
> > > pub_key_algo == SEV_SIG_ALGO_ECDH_SHA256)
> >     {
> >     sha_type = SHA_TYPE_256;
> >     sha_digest = sha_digest_256;
> >     sha_length = sizeof(hmac_sha_256);
> >     }
> > else if (parent_cert->pub_key_algo == SEV_SIG_ALGO_RSA_SHA384 || 
> > parent_cert->pub_key_algo == SEV_SIG_ALGO_ECDSA_SHA384 || 
> > parent_cert->pub_key_algo == SEV_SIG_ALGO_ECDH_SHA384)
> >     {
> >     sha_type = SHA_TYPE_384;
> >     sha_digest = sha_digest_384;
> >     sha_length = sizeof(hmac_sha_512);
> >     }
> >     else
> >     {
> >     break;
> >     }
> > 
> >     // 1. SHA256 hash the cert from Version through pub_key 
> > parameters
> >     // Calculate the digest of the input message   rsa.c ->
> > rsa_pss_verify_msg()
> >     // SHA256/SHA384 hash the cert from the [Version:pub_key] 
> > params
> >     uint32_t pub_key_offset = offsetof(sev_cert, sig_1_usage);
> > // 
> > 16 + sizeof(SEV_PUBKEY)
> >     if (!digest_sha((uint8_t *)child_cert, pub_key_offset, 
> > sha_digest, sha_length, sha_type)) {
> >     break;
> >     }
> > if ((parent_cert->pub_key_algo == SEV_SIG_ALGO_ECDSA_SHA256) ||
> >  (parent_cert->pub_key_algo ==
> > SEV_SIG_ALGO_ECDSA_SHA384) ||
> >  (parent_cert->pub_key_algo ==
> > SEV_SIG_ALGO_ECDH_SHA256)  ||
> >  (parent_cert->pub_key_algo ==
> > SEV_SIG_ALGO_ECDH_SHA384)) {  // ecdsa.c -> sign_verify_msg
> >     ECDSA_SIG *tmp_ecdsa_sig = ECDSA_SIG_new();
> >     BIGNUM *r_big_num = BN_new();
> >     BIGNUM *s_big_num = BN_new();
> > 
> >     // Store the x and y components as separate BIGNUM 
> > objects. The values in the
> >     // SEV certificate are little-endian, must reverse 
> > bytes before storing in BIGNUM
> >     r_big_num = BN_lebin2bn(cert_sig[i].ecdsa.r,
> > sizeof(sev_ecdsa_sig::r), r_big_num);    // LE to BE
> >     s_big_num = BN_lebin2bn(cert_sig[i].ecdsa.s, 
> > sizeof(sev_ecdsa_sig::s), s_big_num);
> > 
> >     // Calling ECDSA_SIG_set0() transfers the memory 
> > management of the values to
> >    

RE: Updating RSA public key generation and signature verification from 1.1.1 to 3.0

2022-09-30 Thread GonzalezVillalobos, Diego via openssl-users
[AMD Official Use Only - General]

Hello Tomas,

There was a logic error in my code, I did not realize that the first iteration 
of the verification was supposed to fail. The verification is working 
correctly! I apologize for my last response. I really appreciate all your help!

Thank you very much,

Diego Gonzalez
--
 

-Original Message-
From: Tomas Mraz  
Sent: Friday, September 30, 2022 1:22 AM
To: GonzalezVillalobos, Diego ; 
openssl-users@openssl.org
Subject: Re: Updating RSA public key generation and signature verification from 
1.1.1 to 3.0

Caution: This message originated from an External Source. Use proper caution 
when opening attachments, clicking links, or responding.


Hi,

unfortunately I do not see anything wrong with the code. Does the 
EVP_DigestVerifyFinal return 0 or negative value? I do not think this is a bug 
in OpenSSL as this API is thoroughly tested and it is highly improbable that 
there would be a bug in the ECDSA verification through this API.

I am currently out of ideas on what could be wrong or how to investigate 
further. Perhaps someone else can chime in on what can be wrong?

Tomas

On Thu, 2022-09-29 at 19:22 +, GonzalezVillalobos, Diego wrote:
> [AMD Official Use Only - General]
>
> Hello Tomas,
>
> So, I made sure that px_size and py_size are equal to the group order 
> (48). I was able to verify successfully using our previous method
> (deprecated) with the new key generation method, but I'm still not 
> able to get the digestverify to work successfully. As a reminder this 
> is how we were verifying before:
>
> // Determine if SHA_TYPE is 256 bit or 384 bit if 
> (parent_cert->pub_key_algo == SEV_SIG_ALGO_RSA_SHA256 || 
> parent_cert->pub_key_algo == SEV_SIG_ALGO_ECDSA_SHA256 ||parent_cert-
> >pub_key_algo == SEV_SIG_ALGO_ECDH_SHA256)
> {
> sha_type = SHA_TYPE_256;
> sha_digest = sha_digest_256;
> sha_length = sizeof(hmac_sha_256);
> }
> else if (parent_cert->pub_key_algo == SEV_SIG_ALGO_RSA_SHA384 || 
> parent_cert->pub_key_algo == SEV_SIG_ALGO_ECDSA_SHA384 || 
> parent_cert->pub_key_algo == SEV_SIG_ALGO_ECDH_SHA384)
> {
> sha_type = SHA_TYPE_384;
> sha_digest = sha_digest_384;
> sha_length = sizeof(hmac_sha_512);
> }
> else
> {
> break;
> }
>
> // 1. SHA256 hash the cert from Version through pub_key 
> parameters
> // Calculate the digest of the input message   rsa.c ->
> rsa_pss_verify_msg()
> // SHA256/SHA384 hash the cert from the [Version:pub_key] 
> params
> uint32_t pub_key_offset = offsetof(sev_cert, sig_1_usage); // 
> 16 + sizeof(SEV_PUBKEY)
> if (!digest_sha((uint8_t *)child_cert, pub_key_offset, 
> sha_digest, sha_length, sha_type)) {
> break;
> }
> if ((parent_cert->pub_key_algo == SEV_SIG_ALGO_ECDSA_SHA256) ||
>  (parent_cert->pub_key_algo ==
> SEV_SIG_ALGO_ECDSA_SHA384) ||
>  (parent_cert->pub_key_algo ==
> SEV_SIG_ALGO_ECDH_SHA256)  ||
>  (parent_cert->pub_key_algo ==
> SEV_SIG_ALGO_ECDH_SHA384)) {  // ecdsa.c -> sign_verify_msg
> ECDSA_SIG *tmp_ecdsa_sig = ECDSA_SIG_new();
> BIGNUM *r_big_num = BN_new();
> BIGNUM *s_big_num = BN_new();
>
> // Store the x and y components as separate BIGNUM 
> objects. The values in the
> // SEV certificate are little-endian, must reverse 
> bytes before storing in BIGNUM
> r_big_num = BN_lebin2bn(cert_sig[i].ecdsa.r,
> sizeof(sev_ecdsa_sig::r), r_big_num);// LE to BE
> s_big_num = BN_lebin2bn(cert_sig[i].ecdsa.s, 
> sizeof(sev_ecdsa_sig::s), s_big_num);
>
> // Calling ECDSA_SIG_set0() transfers the memory 
> management of the values to
> // the ECDSA_SIG object, and therefore the values that 
> have been passed
> // in should not be freed directly after this function 
> has been called
> if (ECDSA_SIG_set0(tmp_ecdsa_sig, r_big_num,
> s_big_num) != 1) {
> BN_free(s_big_num);   // Frees
> BIGNUMs manually here
> BN_free(r_big_num);
> ECDSA_SIG_free(tmp_ecdsa_sig);
> continue;
> }
> EC_KEY *tmp_ec_key =
> EVP_PKEY_get1_EC_KEY(parent_signing_key); // Make a local key so you 
> can free it later
> if (ECDSA_do_verify(sha_dige

RE: Updating RSA public key generation and signature verification from 1.1.1 to 3.0

2022-09-30 Thread Michael Wojcik via openssl-users
> From: openssl-users  On Behalf Of Tomas
> Mraz
> Sent: Friday, 30 September, 2022 00:22
> 
> unfortunately I do not see anything wrong with the code. Does the
> EVP_DigestVerifyFinal return 0 or negative value? I do not think this
> is a bug in OpenSSL as this API is thoroughly tested and it is highly
> improbable that there would be a bug in the ECDSA verification through
> this API.
> 
> I am currently out of ideas on what could be wrong or how to
> investigate further. Perhaps someone else can chime in on what can be
> wrong?

Coincidentally, just yesterday I was helping someone debug a DigestVerify 
issue. We were consistently getting the "first octet is invalid" error out of 
the RSA PSS signature verification code, but the same inputs worked with 
openssl dgst.

I wrote a fresh minimal program from scratch (really minimal, with hard-coded 
filenames for the inputs), and it worked fine as soon as it compiled cleanly.

I'd suggest trying that. Get it working in a minimal program first. Make sure 
you have all the correct OpenSSL headers, and there are no compilation 
warnings. Then integrate that code into your application.

(I didn't have the original application to go back to, in my case, and the 
person I was working with is in another timezone and had left for the day.)

-- 
Michael Wojcik
Distinguished Engineer, Application Modernization and Connectivity




Re: Updating RSA public key generation and signature verification from 1.1.1 to 3.0

2022-09-30 Thread Tomas Mraz
     printf("Failed Final Verify
> %s\n",ERR_error_string(ERR_get_error(),NULL));
>     cout << "EC Verify error" << endl;
>     break;
>     }
> 
>     found_match = true;
>     cout << "SEV EC verification Succesful" << endl;
> 
>     if (verify_md_ctx)
>     EVP_MD_CTX_free(verify_md_ctx);
> 
>     break;
>     }
> 
> The only difference still is using the der signature; besides that,
> it is the same. Could it be a bug?
> 
> Thank you,
> 
> Diego Gonzalez
> -
> -
>  
> 
> -Original Message-
> From: Tomas Mraz  
> Sent: Thursday, September 29, 2022 1:12 AM
> To: GonzalezVillalobos, Diego ;
> openssl-users@openssl.org
> Subject: Re: Updating RSA public key generation and signature
> verification from 1.1.1 to 3.0
> 
> Caution: This message originated from an External Source. Use proper
> caution when opening attachments, clicking links, or responding.
> 
> 
> Hi,
> 
> comments below.
> 
> On Wed, 2022-09-28 at 22:12 +, GonzalezVillalobos, Diego wrote:
> > [AMD Official Use Only - General]
> > 
> > Hello Tomas,
> > 
> > I generated the key as you suggested, and I am no longer getting an
> > error message! Thank you for that. Here is how I'm generating the
> > key
> > now:
> > 
> > // SEV certificate are little-endian, must reverse bytes before 
> > generating key
> >     if ((cert->pub_key_algo == SEV_SIG_ALGO_ECDSA_SHA256)
> > ||
> >     (cert->pub_key_algo == SEV_SIG_ALGO_ECDSA_SHA384))
> > {
> >     //Grab x param and flip bytes to BE
> >     memcpy(px, >pub_key.ecdsa.qx,
> > ec_group_order);
> >     if(!sev::reverse_bytes(px, sizeof(px)))
> >     break;
> >     //Grab y param and flip bytes to BE
> >     memcpy(py, >pub_key.ecdsa.qy,
> > ec_group_order);
> >     if(!sev::reverse_bytes(py, sizeof(py)))
> >     break;
> >     }
> >     else if ((cert->pub_key_algo ==
> > SEV_SIG_ALGO_ECDH_SHA256)  ||
> >     (cert->pub_key_algo ==
> > SEV_SIG_ALGO_ECDH_SHA384)) 
> > {
> >     //Grab x param and flip bytes to BE
> >     memcpy(px, >pub_key.ecdh.qx, ec_group_order);
> >     if(!sev::reverse_bytes(px, sizeof(px)))
> >     break;
> >     //Grab y param and flip bytes to BE
> >     memcpy(py, >pub_key.ecdh.qy, ec_group_order);
> >     if(!sev::reverse_bytes(py, sizeof(py)))
> >     break;
> >     }
> > 
> >     int px_size = sizeof(px)/sizeof(*px);
> >     int py_size = sizeof(py)/sizeof(*py);
> > 
> >     // Will contain x and y components
> >     unsigned char public_key_xy[1 + px_size + py_size] =
> > {0};
> > 
> >     //Add point conversion as first value
> >     public_key_xy[0] = POINT_CONVERSION_UNCOMPRESSED;
> > 
> >     //Add x components after point compression
> >     memcpy(public_key_xy + 1, px, px_size);
> >     //Add y components after x
> >     memcpy(public_key_xy + px_size + 1, py ,py_size);
> > 
> >     // int nid = EC_curve_nist2nid("P-384");   //
> > NID_secp384r1
> > 
> >     OSSL_PARAM_BLD *params_build = OSSL_PARAM_BLD_new();
> > 
> >     if ( params_build == NULL ) {
> >     cout << "Params build fails" << endl;
> >     break;
> >     }
> > 
> >     if (!OSSL_PARAM_BLD_push_utf8_string(params_build,
> > OSSL_PKEY_PARAM_GROUP_NAME, "P-384", 0)) {
> >     cout<< "Push EC curve to build fails" << endl;
> >     break;
> >     }
> > 
> >     if (!OSSL_PARAM_BLD_push_octet_string(params_build,
> > OSSL_PKEY_PARAM_PUB_KEY, public_key_xy, sizeof(public_key_xy))) {
> >     cout << "Error: failed to push qx into param
> > build."
> > << endl;
> >     break;
> >     }
> > 
> >     OSSL_PARAM *params =
&

RE: Updating RSA public key generation and signature verification from 1.1.1 to 3.0

2022-09-29 Thread GonzalezVillalobos, Diego via openssl-users
SHA384) ||
 (parent_cert->pub_key_algo == SEV_SIG_ALGO_ECDH_SHA256)  ||
 (parent_cert->pub_key_algo == SEV_SIG_ALGO_ECDH_SHA384)) { 
 // ecdsa.c -> sign_verify_msg

ECDSA_SIG *tmp_ecdsa_sig = ECDSA_SIG_new();
BIGNUM *r_big_num = BN_new();
BIGNUM *s_big_num = BN_new();
uint32_t sig_len;
unsigned char* der_sig = NULL;;

// Store the x and y components as separate BIGNUM objects. The 
values in the
// SEV certificate are little-endian, must reverse bytes before 
storing in BIGNUM
r_big_num = BN_lebin2bn(cert_sig[i].ecdsa.r, 
sizeof(sev_ecdsa_sig::r), r_big_num);// LE to BE
s_big_num = BN_lebin2bn(cert_sig[i].ecdsa.s, 
sizeof(sev_ecdsa_sig::s), s_big_num);

// Calling ECDSA_SIG_set0() transfers the memory management of 
the values to
// the ECDSA_SIG object, and therefore the values that have 
been passed
// in should not be freed directly after this function has been 
called
if (ECDSA_SIG_set0(tmp_ecdsa_sig, r_big_num,s_big_num) != 1) {
BN_free(s_big_num); // FreesBIGNUMs manually here
BN_free(r_big_num);
ECDSA_SIG_free(tmp_ecdsa_sig);
break;
}

int der_sig_len = i2d_ECDSA_SIG(tmp_ecdsa_sig, _sig);
// der_sig = static_cast(OPENSSL_malloc(der_sig_len));
// unsigned char* der_iter = der_sig;
// der_sig_len = i2d_ECDSA_SIG(tmp_ecdsa_sig, _iter); // <= 
bugfix here


if (der_sig_len == 0) {
cout << "sig length invalid" << endl;
break;
}

if (der_sig == NULL) {
cout << "sig generation failed" << endl;
break;
}

// loop through the array elements
for (size_t i = 0; i < der_sig_len; i++) {
cout << der_sig[i] << ' ';
}

verify_md_ctx = EVP_MD_CTX_new();


if (!verify_md_ctx) {
cout << "Error md verify context " << endl;;
break;
}

if (EVP_DigestVerifyInit(verify_md_ctx, NULL, 
(parent_cert->pub_key_algo == SEV_SIG_ALGO_ECDSA_SHA256 || 
parent_cert->pub_key_algo == SEV_SIG_ALGO_ECDH_SHA256) ? EVP_sha256(): 
EVP_sha384(), NULL, parent_signing_key) <= 0) {
cout << "Init fails " << endl;
break;
}

if (EVP_DigestVerifyUpdate(verify_md_ctx, (uint8_t 
*)child_cert, pub_key_offset) <= 0){// Calls SHA256_UPDATE
cout << "updating digest fails" << endl;
break;
}

int ret = EVP_DigestVerifyFinal(verify_md_ctx, der_sig, 
der_sig_len);
if (ret == 0) {
cout << "EC Verify digest fails" << endl;
break;
} else if (ret < 0) {
printf("Failed Final Verify 
%s\n",ERR_error_string(ERR_get_error(),NULL));
cout << "EC Verify error" << endl;
break;
}

found_match = true;
cout << "SEV EC verification Succesful" << endl;

if (verify_md_ctx)
EVP_MD_CTX_free(verify_md_ctx);

break;
}

The only difference still is using the der signature; besides that, it is the 
same. Could it be a bug?

Thank you,

Diego Gonzalez
--------------------------
 

-Original Message-
From: Tomas Mraz  
Sent: Thursday, September 29, 2022 1:12 AM
To: GonzalezVillalobos, Diego ; 
openssl-users@openssl.org
Subject: Re: Updating RSA public key generation and signature verification from 
1.1.1 to 3.0

Caution: This message originated from an External Source. Use proper caution 
when opening attachments, clicking links, or responding.


Hi,

comments below.

On Wed, 2022-09-28 at 22:12 +, GonzalezVillalobos, Diego wrote:
> [AMD Official Use Only - General]
>
> Hello Tomas,
>
> I generated the key as you suggested, and I am no longer getting an 
> error message! Thank you for that. Here is how I'm generating the key
> now:
>
> // SEV certificate are little-endian, must reverse bytes before 
> generating key
> if ((cert->pub_key_algo == SEV_SIG_ALGO_ECDSA_SHA256) ||
> (cert->pu

Re: Updating RSA public key generation and signature verification from 1.1.1 to 3.0

2022-09-29 Thread Tomas Mraz
Hi,

comments below.

On Wed, 2022-09-28 at 22:12 +, GonzalezVillalobos, Diego wrote:
> [AMD Official Use Only - General]
> 
> Hello Tomas,
> 
> I generated the key as you suggested, and I am no longer getting an
> error message! Thank you for that. Here is how I'm generating the key
> now:
> 
> // SEV certificate are little-endian, must reverse bytes before
> generating key
>     if ((cert->pub_key_algo == SEV_SIG_ALGO_ECDSA_SHA256) ||
>     (cert->pub_key_algo == SEV_SIG_ALGO_ECDSA_SHA384)) {
>     //Grab x param and flip bytes to BE
>     memcpy(px, >pub_key.ecdsa.qx, ec_group_order);
>     if(!sev::reverse_bytes(px, sizeof(px)))
>     break;
>     //Grab y param and flip bytes to BE
>     memcpy(py, >pub_key.ecdsa.qy, ec_group_order);
>     if(!sev::reverse_bytes(py, sizeof(py)))
>     break;
>     }
>     else if ((cert->pub_key_algo ==
> SEV_SIG_ALGO_ECDH_SHA256)  ||
>     (cert->pub_key_algo == SEV_SIG_ALGO_ECDH_SHA384))
> {
>     //Grab x param and flip bytes to BE
>     memcpy(px, >pub_key.ecdh.qx, ec_group_order);
>     if(!sev::reverse_bytes(px, sizeof(px)))
>     break;
>     //Grab y param and flip bytes to BE
>     memcpy(py, >pub_key.ecdh.qy, ec_group_order);
>     if(!sev::reverse_bytes(py, sizeof(py)))
>     break;
>     }
> 
>     int px_size = sizeof(px)/sizeof(*px);
>     int py_size = sizeof(py)/sizeof(*py);
> 
>     // Will contain x and y components
>     unsigned char public_key_xy[1 + px_size + py_size] = {0};
> 
>     //Add point conversion as first value
>     public_key_xy[0] = POINT_CONVERSION_UNCOMPRESSED;
> 
>     //Add x components after point compression
>     memcpy(public_key_xy + 1, px, px_size);
>     //Add y components after x
>     memcpy(public_key_xy + px_size + 1, py ,py_size);
>     
>     // int nid = EC_curve_nist2nid("P-384");   //
> NID_secp384r1
> 
>     OSSL_PARAM_BLD *params_build = OSSL_PARAM_BLD_new();
> 
>     if ( params_build == NULL ) {
>     cout << "Params build fails" << endl;
>     break;
>     }
> 
>     if (!OSSL_PARAM_BLD_push_utf8_string(params_build,
> OSSL_PKEY_PARAM_GROUP_NAME, "P-384", 0)) {
>     cout<< "Push EC curve to build fails" << endl;
>     break;
>     }
> 
>     if (!OSSL_PARAM_BLD_push_octet_string(params_build,
> OSSL_PKEY_PARAM_PUB_KEY, public_key_xy, sizeof(public_key_xy))) {
>     cout << "Error: failed to push qx into param build."
> << endl;
>     break;
>     }
>     
>     OSSL_PARAM *params =
> OSSL_PARAM_BLD_to_param(params_build);
> 
>     if ( params == NULL ) {
>     cout << "Error: building parameters." << endl;
>     break;
>     }
> 
>     OSSL_PARAM_BLD_free(params_build);
>     
>     key_gen_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
> 
>     if(EVP_PKEY_fromdata_init(key_gen_ctx) != 1) {
>     cout << "failed to initialize key creation." << endl;
>     break;
>     }
> 
>     if(EVP_PKEY_fromdata(key_gen_ctx, _pub_key,
> EVP_PKEY_PUBLIC_KEY, params) != 1) {
>     cout << "key generation breaks" << endl;
>     printf("Failed Final Verify
> %s\n",ERR_error_string(ERR_get_error(),NULL));
>     break;
>     }
> 
>     if (EVP_PKEY_get_base_id(evp_pub_key) != EVP_PKEY_EC) {
>     cout << "wrong key type" << endl;
>     break;
>     }
>     }
> 
>     if (!evp_pub_key) {
>     cout << "no evp pkey" << endl;
>     break;
>     }
>     cout << "compile key succesful" << endl;
>     cmd_ret = STATUS_SUCCESS;
> 
> Although the key generation works and I'm not getting a verify error
> anymore, I am still unsuccessful on verifying the digest. It keeps
> failing (returning 0). Here is how I'm currently trying to do the
> verification.

Are you sure the px_size and py_size is equal to the group order? The x
and y values must be padded to the group order with 0 (at the start
because the values need to be BE).

> ECDSA_SIG *tmp_ecdsa_sig = ECDSA_SIG_new();
>     BIGNUM *r_big_num = BN_new();
>     BIGNUM *s_big_num = BN_new();
>     uint32_t sig_len;
>     unsigned char* der_sig;
> 
>     // Store the x and y components as separate BIGNUM
> objects. The values in the
>     // SEV certificate are little-endian, must reverse
> bytes before storing in BIGNUM
>     r_big_num = BN_lebin2bn(cert_sig[i].ecdsa.r,
> 

RE: Updating RSA public key generation and signature verification from 1.1.1 to 3.0

2022-09-28 Thread GonzalezVillalobos, Diego via openssl-users
// the ECDSA_SIG object, and therefore the values that have 
been passed
// in should not be freed directly after this function has been 
called
if (ECDSA_SIG_set0(tmp_ecdsa_sig, r_big_num,s_big_num) != 1) {
BN_free(s_big_num); // FreesBIGNUMs manually here
BN_free(r_big_num);
ECDSA_SIG_free(tmp_ecdsa_sig);
break;
}

int der_sig_len = i2d_ECDSA_SIG(tmp_ecdsa_sig, NULL);
der_sig = static_cast(OPENSSL_malloc(der_sig_len));
unsigned char* der_iter = der_sig;
der_sig_len = i2d_ECDSA_SIG(tmp_ecdsa_sig, _iter); // <= 
bugfix here

if (der_sig_len == 0) {
cout << "sig length invalid" << endl;
break;
}

if (der_sig == NULL) {
cout << "sig generation failed" << endl;
break;
}


verify_md_ctx = EVP_MD_CTX_new();


if (!verify_md_ctx) {
cout << "Error md verify context " << endl;;
break;
}

if (EVP_DigestVerifyInit(verify_md_ctx, NULL, 
(parent_cert->pub_key_algo == SEV_SIG_ALGO_ECDSA_SHA256 || 
parent_cert->pub_key_algo == SEV_SIG_ALGO_ECDH_SHA256) ? EVP_sha256(): 
EVP_sha384(), NULL, parent_signing_key) <= 0) {
cout << "Init fails " << endl;
break;
}

if (EVP_DigestVerifyUpdate(verify_md_ctx, (uint8_t 
*)child_cert, pub_key_offset) <= 0){// Calls SHA256_UPDATE
cout << "updating digest fails" << endl;
break;
}

int ret = EVP_DigestVerifyFinal(verify_md_ctx, der_sig, 
der_sig_len);
cout << ret << endl;
if (ret == 0) {
cout << "EC Verify digest fails" << endl;
break;
} else if (ret < 0) {
printf("Failed Final Verify 
%s\n",ERR_error_string(ERR_get_error(),NULL));
cout << "EC Verify error" << endl;
break;
}

found_match = true;
cout << "SEV EC verification Succesful" << endl;

Could it be because I'm creating a ECDSA SIG object and then turning it into a 
der format to verify? Again, suggestions would be appreciated.

Thank you!

Diego Gonzalez Villalobos
--
 

-Original Message-
From: Tomas Mraz  
Sent: Friday, September 23, 2022 1:17 AM
To: GonzalezVillalobos, Diego ; 
openssl-users@openssl.org
Subject: Re: Updating RSA public key generation and signature verification from 
1.1.1 to 3.0

Caution: This message originated from an External Source. Use proper caution 
when opening attachments, clicking links, or responding.


Please look at the answer in this question in GitHub:

https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fopenssl%2Fopenssl%2Fissues%2F19219%23issuecomment-1247782572data=05%7C01%7CDiego.GonzalezVillalobos%40amd.com%7C49cb5498fa2142b3c73f08da9d2b3799%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637995106207913021%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7Csdata=S%2FIfBL5bnOa%2Fa2owmcihtZlG4AxTYCWDkaGpmJdid%2Fw%3Dreserved=0

Matt Caswell's answer to very similar question is presented there.

I'm copying the answer here for convenience:

You are attempting to create an EC public key using the "x" and "y"
parameters - but no such parameters exist. The list of available EC parameters 
is on this page:

https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.openssl.org%2Fdocs%2Fman3.0%2Fman7%2FEVP_PKEY-EC.htmldata=05%7C01%7CDiego.GonzalezVillalobos%40amd.com%7C49cb5498fa2142b3c73f08da9d2b3799%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637995106207913021%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7Csdata=dRWekElnVV5leTg6ZN0k9LwQq1Sivf2Hx%2BZrY7YPajE%3Dreserved=0

For your purposes you need to use the OSSL_PKEY_PARAM_PUB_KEY parameter
("pub") to supply the public key. It needs to be an octet string with the value 
POINT_CONVERSION_UNCOMPRESSED at the start followed by the x and y co-ords 
concatenated together. For that curve, x and y need to be zero padded to be 32 
bytes long each. There is an example of doing this on the EVP_PKEY_fromdata man 
page. Actually the example is is for EVP_PK

Re: Updating RSA public key generation and signature verification from 1.1.1 to 3.0

2022-09-23 Thread Tomas Mraz
new();
>     uint32_t sig_len;
>     unsigned char *p;
> 
>     // Store the x and y components as separate BIGNUM
> objects. The values in the
>     // SEV certificate are little-endian, must reverse
> bytes before storing in BIGNUM
>     r_big_num = BN_lebin2bn(cert_sig[i].ecdsa.r,
> sizeof(sev_ecdsa_sig::r), r_big_num);    // LE to BE
>     s_big_num = BN_lebin2bn(cert_sig[i].ecdsa.s,
> sizeof(sev_ecdsa_sig::s), s_big_num);
> 
>     // Calling ECDSA_SIG_set0() transfers the memory
> management of the values to
>     // the ECDSA_SIG object, and therefore the values
> that have been passed
>     // in should not be freed directly after this
> function has been called
>     if (ECDSA_SIG_set0(tmp_ecdsa_sig, r_big_num,
> s_big_num) != 1) {
>     BN_free(s_big_num);   // Frees
> BIGNUMs manually here
>     BN_free(r_big_num);
>     ECDSA_SIG_free(tmp_ecdsa_sig);
>     break;
>     }
> 
>     sig_len = i2d_ECDSA_SIG(tmp_ecdsa_sig, NULL);
>     unsigned char signature[sig_len];
> 
>     p = signature;
> 
>     sig_len = i2d_ECDSA_SIG(tmp_ecdsa_sig, );
> 
> 
>     if (signature == NULL) {
>     cout << "sig mem failed" << endl;
>     break;
>     }
> 
>     if (sig_len == 0)
>     cout << "sig length invalid" << endl;
> 
>     verify_md_ctx = EVP_MD_CTX_new();
> 
> 
>     if (!verify_md_ctx) {
>     cout << "Error md verify context " << endl;;
>     break;
>     }
> 
>     if (EVP_DigestVerifyInit(verify_md_ctx, NULL,
> (parent_cert->pub_key_algo == SEV_SIG_ALGO_ECDSA_SHA256 ||
> parent_cert->pub_key_algo == SEV_SIG_ALGO_ECDH_SHA256) ? EVP_sha256()
> : EVP_sha384(), NULL, parent_signing_key) <= 0) {
>     cout << "Init fails " << endl;
>     break;
>     }
> 
>     if (EVP_DigestVerifyUpdate(verify_md_ctx, child_cert,
> pub_key_offset) <= 0){    // Calls SHA256_UPDATE
>     cout << "updating digest fails" << endl;
>     break;
>     }
> 
>     int ret = EVP_DigestVerifyFinal(verify_md_ctx,
> signature, sig_len);
>         cout << ret << endl;
>     if (ret == 0) {
>     cout << "EC Verify digest fails" << endl;
>     break; 
>     } else if (ret < 0) {
>     printf("Failed Final Verify
> %s\n",ERR_error_string(ERR_get_error(),NULL));
>     cout << "EC Verify error" << endl;
>     break;
>     }
> 
>     found_match = true;
>     cout << "SEV EC verification Succesful" << endl;
> 
> 
> My current output when I reach EVP_DigestVerifyFinal is showing this
> error:
> Failed Final Verify error:0395:digital envelope routines::no
> operation set
> 
> I have been playing around with it for a while, but I am stuck at
> this point. Any advice would be appreciated.
> 
> Thank you,
> 
> Diego Gonzalez Villalobos
> -
> -
>  
> 
> -Original Message-
> From: Tomas Mraz  
> Sent: Friday, September 9, 2022 10:36 AM
> To: GonzalezVillalobos, Diego ;
> openssl-users@openssl.org
> Subject: Re: Updating RSA public key generation and signature
> verification from 1.1.1 to 3.0
> 
> [CAUTION: External Email]
> 
> On Thu, 2022-09-08 at 16:10 +, GonzalezVillalobos, Diego via
> openssl-users wrote:
> > [AMD Official Use Only - General]
> > 
> > Hello everyone,
> > 
> > I am currently working on updating a signature verification
> > function 
> > in C++ and I am a bit stuck. I am trying to replace the deprecated
> > 1.1.1 functions to the appropriate 3.0 versions. The function takes
> > in 
> > 2 certificate objects (parent and cert), which are not x509 
> > certificates, but certificates the company had previously defined.
> > Using the contents from parent we create an RSA public key and
> > using 
> > the contents from cert we create the digest and grab the signature
> > to 
> > verify.
> > 
> > In the 1.1.1 version we were using the RSA Object and the
> > rsa_set0_key 
> > function to create the RSA public key and then used
> > RSA_public_decrypt 
> > to decrypt the signature and RSA_verify_PKCS1_PSS to verify it.
> > This 
> > whole workflow is now deprecated.
> > 
> ...
> > Is this the correct way of creating RSA keys now? Where is my logic
> > failing? Can the same type of procedure even be done on 3.0? Any 
> > advice would be really appreciated.
> > 
> 
> In the original code you seem to be using PSS padding for
> verification.
> Did you try to set the PSS padding on the digest verify context? See
> demos/signature/rsa_pss_hash.c on how to do it.
> 
> --
> Tomáš Mráz, OpenSSL

-- 
Tomáš Mráz, OpenSSL



RE: Updating RSA public key generation and signature verification from 1.1.1 to 3.0

2022-09-22 Thread GonzalezVillalobos, Diego via openssl-users
lt;< "EC Verify digest fails" << endl;
break; 
} else if (ret < 0) {
printf("Failed Final Verify 
%s\n",ERR_error_string(ERR_get_error(),NULL));
cout << "EC Verify error" << endl;
break;
}

found_match = true;
cout << "SEV EC verification Succesful" << endl;


My current output when I reach EVP_DigestVerifyFinal is showing this error:
Failed Final Verify error:0395:digital envelope routines::no operation set

I have been playing around with it for a while, but I am stuck at this point. 
Any advice would be appreciated.

Thank you,

Diego Gonzalez Villalobos
--
 

-Original Message-
From: Tomas Mraz  
Sent: Friday, September 9, 2022 10:36 AM
To: GonzalezVillalobos, Diego ; 
openssl-users@openssl.org
Subject: Re: Updating RSA public key generation and signature verification from 
1.1.1 to 3.0

[CAUTION: External Email]

On Thu, 2022-09-08 at 16:10 +, GonzalezVillalobos, Diego via openssl-users 
wrote:
> [AMD Official Use Only - General]
>
> Hello everyone,
>
> I am currently working on updating a signature verification function 
> in C++ and I am a bit stuck. I am trying to replace the deprecated
> 1.1.1 functions to the appropriate 3.0 versions. The function takes in 
> 2 certificate objects (parent and cert), which are not x509 
> certificates, but certificates the company had previously defined.
> Using the contents from parent we create an RSA public key and using 
> the contents from cert we create the digest and grab the signature to 
> verify.
>
> In the 1.1.1 version we were using the RSA Object and the rsa_set0_key 
> function to create the RSA public key and then used RSA_public_decrypt 
> to decrypt the signature and RSA_verify_PKCS1_PSS to verify it. This 
> whole workflow is now deprecated.
>
...
> Is this the correct way of creating RSA keys now? Where is my logic 
> failing? Can the same type of procedure even be done on 3.0? Any 
> advice would be really appreciated.
>

In the original code you seem to be using PSS padding for verification.
Did you try to set the PSS padding on the digest verify context? See 
demos/signature/rsa_pss_hash.c on how to do it.

--
Tomáš Mráz, OpenSSL


Re: Updating RSA public key generation and signature verification from 1.1.1 to 3.0

2022-09-09 Thread Tomas Mraz
On Thu, 2022-09-08 at 16:10 +, GonzalezVillalobos, Diego via
openssl-users wrote:
> [AMD Official Use Only - General]
> 
> Hello everyone,
>  
> I am currently working on updating a signature verification function
> in C++ and I am a bit stuck. I am trying to replace the deprecated
> 1.1.1 functions to the appropriate 3.0 versions. The function takes
> in 2 certificate objects (parent and cert), which are not x509
> certificates, but certificates the company had previously defined.
> Using the contents from parent we create an RSA public key and using
> the contents from cert we create the digest and grab the signature to
> verify.
>  
> In the 1.1.1 version we were using the RSA Object and the
> rsa_set0_key function to create the RSA public key and then used
> RSA_public_decrypt to decrypt the signature and RSA_verify_PKCS1_PSS
> to verify it. This whole workflow is now deprecated.
> 
...
> Is this the correct way of creating RSA keys now? Where is my logic
> failing? Can the same type of procedure even be done on 3.0? Any
> advice would be really appreciated.
>  

In the original code you seem to be using PSS padding for verification.
Did you try to set the PSS padding on the digest verify context? See
demos/signature/rsa_pss_hash.c on how to do it.

-- 
Tomáš Mráz, OpenSSL



Updating RSA public key generation and signature verification from 1.1.1 to 3.0

2022-09-08 Thread GonzalezVillalobos, Diego via openssl-users
[AMD Official Use Only - General]

Hello everyone,

I am currently working on updating a signature verification function in C++ and 
I am a bit stuck. I am trying to replace the deprecated 1.1.1 functions to the 
appropriate 3.0 versions. The function takes in 2 certificate objects (parent 
and cert), which are not x509 certificates, but certificates the company had 
previously defined. Using the contents from parent we create an RSA public key 
and using the contents from cert we create the digest and grab the signature to 
verify.

In the 1.1.1 version we were using the RSA Object and the rsa_set0_key function 
to create the RSA public key and then used RSA_public_decrypt to decrypt the 
signature and RSA_verify_PKCS1_PSS to verify it. This whole workflow is now 
deprecated.

//OPENSSL 1.1.1 Code
SEV_ERROR_CODE AMDCert::amd_cert_validate_sig(const amd_cert *cert,
  const amd_cert *parent,
  ePSP_DEVICE_TYPE device_type)
{
SEV_ERROR_CODE cmd_ret = ERROR_INVALID_CERTIFICATE;
hmac_sha_256 sha_digest_256;
hmac_sha_512 sha_digest_384;
SHA_TYPE algo = SHA_TYPE_256;
uint8_t *sha_digest = NULL;
size_t sha_length = 0;

RSA *rsa_pub_key = NULL;
BIGNUM *modulus = NULL;
BIGNUM *pub_exp = NULL;
EVP_MD_CTX* md_ctx = NULL;
uint32_t sig_len = cert->modulus_size/8;

uint32_t digest_len = 0;
uint8_t decrypted[AMD_CERT_KEY_BYTES_4K] = {0}; // TODO wrong length
uint8_t signature[AMD_CERT_KEY_BYTES_4K] = {0};
uint32_t fixed_offset = offsetof(amd_cert, pub_exp);// 64 bytes

do {
if (!cert || !parent) {
cmd_ret = ERROR_INVALID_PARAM;
   break;
}

// Set SHA_TYPE to 256 bit or 384 bit depending on device_type
if (device_type == PSP_DEVICE_TYPE_NAPLES) {
algo = SHA_TYPE_256;
sha_digest = sha_digest_256;
sha_length = sizeof(hmac_sha_256);
}
else /*if (ROME/MILAN)*/ {
algo = SHA_TYPE_384;
sha_digest = sha_digest_384;
sha_length = sizeof(hmac_sha_512);
}

// Memzero all the buffers
memset(sha_digest, 0, sha_length);
memset(decrypted, 0, sizeof(decrypted));
memset(signature, 0, sizeof(signature));

// New up the RSA key
rsa_pub_key = RSA_new();

// Convert the parent to an RSA key to pass into RSA_verify
modulus = BN_lebin2bn((uint8_t *)>modulus, 
parent->modulus_size/8, NULL);  // n// New's up BigNum
pub_exp = BN_lebin2bn((uint8_t *)>pub_exp, 
parent->pub_exp_size/8, NULL);   // e
if (RSA_set0_key(rsa_pub_key, modulus, pub_exp, NULL) != 1)
break;

 // Create digest from certificate
md_ctx = EVP_MD_CTX_create();
if (EVP_DigestInit(md_ctx, (algo == SHA_TYPE_256) ? EVP_sha256() : 
EVP_sha384()) <= 0)
break;
if (EVP_DigestUpdate(md_ctx, cert, fixed_offset) <= 0) // Calls 
SHA256_UPDATE
break;
if (EVP_DigestUpdate(md_ctx, >pub_exp, cert->pub_exp_size/8) <= 0)
break;
if (EVP_DigestUpdate(md_ctx, >modulus, cert->modulus_size/8) <= 0)
break;
EVP_DigestFinal(md_ctx, sha_digest, _len);

// Swap the bytes of the signature
memcpy(signature, >sig, parent->modulus_size/8);
if (!sev::reverse_bytes(signature, parent->modulus_size/8))
break;

// Now we will verify the signature. Start by a RAW decrypt of the 
signature
if (RSA_public_decrypt(sig_len, signature, decrypted, rsa_pub_key, 
RSA_NO_PADDING) == -1)
break;

// Verify the data
// SLen of -2 means salt length is recovered from the signature
if (RSA_verify_PKCS1_PSS(rsa_pub_key, sha_digest,
(algo == SHA_TYPE_256) ? EVP_sha256() : 
EVP_sha384(),
decrypted, -2) != 1)
{
break;
}

cmd_ret = STATUS_SUCCESS;
} while (0);

// Free the keys and contexts
if (rsa_pub_key)
RSA_free(rsa_pub_key);

if (md_ctx)
EVP_MD_CTX_free(md_ctx);

return cmd_ret;
}

My current attempt to do this update is first creating an EVP_PKEY object which 
will now store the public key and inputting the same data from parent by using 
the EVP_PKEY_fromdata generation function. I build my OSSL_PARAMETERS using 
OSSL_PARAM_BLD to which I push the data from parent. Lastly for the 
verification I am using the EVP_DigestVerifyFinal procedure. I create the 
digest using EVP_DigestVerifyInit and EVP_DigestVerifyUpdate and passing in the 
same data from cert that we were using in the 1.1.1 version of the function. I 
have tried different approaches to both creating the key and the verification 
procedure, but I cannot seem to get it to work.

// OPENSSL 3.0 code
SEV_ERROR_CODE