[PATCH] lib: rsa: Extract public key from private key if keyfile argument is used

If the 'keyfile' (-G) argument is used, there is little value to require 'keydir' (-k) argument since the public key can also be extracted from the private key itself.
Signed-off-by: Donald Chan hoiho@lab126.com --- lib/rsa/rsa-sign.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-)
diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c index f4ed11e74a..f70f352311 100644 --- a/lib/rsa/rsa-sign.c +++ b/lib/rsa/rsa-sign.c @@ -49,16 +49,16 @@ static int rsa_err(const char *msg) }
/** - * rsa_pem_get_pub_key() - read a public key from a .crt file + * rsa_pem_get_pub_key() - read a public key from a private key file or .crt file * - * @keydir: Directory containins the key - * @name Name of key file (will have a .crt extension) + * @keydir: Directory containing the key, can be NULL + * @name Name of key file (will apply a .crt extension if keydir is not NULL) * @evpp Returns EVP_PKEY object, or NULL on failure * @return 0 if ok, -ve on error (in which case *evpp will be set to NULL) */ static int rsa_pem_get_pub_key(const char *keydir, const char *name, EVP_PKEY **evpp) { - char path[1024]; + char path[1024] = {0}; EVP_PKEY *key = NULL; X509 *cert; FILE *f; @@ -68,7 +68,10 @@ static int rsa_pem_get_pub_key(const char *keydir, const char *name, EVP_PKEY ** return -EINVAL;
*evpp = NULL; - snprintf(path, sizeof(path), "%s/%s.crt", keydir, name); + if (keydir && name) + snprintf(path, sizeof(path), "%s/%s.crt", keydir, name); + else if (name) + snprintf(path, sizeof(path), "%s", name); f = fopen(path, "r"); if (!f) { fprintf(stderr, "Couldn't open RSA certificate: '%s': %s\n", @@ -76,7 +79,13 @@ static int rsa_pem_get_pub_key(const char *keydir, const char *name, EVP_PKEY ** return -EACCES; }
- /* Read the certificate */ + /* See if it contains a PEM private key? */ + if (PEM_read_PrivateKey(f, evpp, NULL, path)) { + fclose(f); + return 0; + } + + /* Not a PEM private key, read the certificate */ cert = NULL; if (!PEM_read_X509(f, &cert, NULL, NULL)) { rsa_err("Couldn't read certificate"); @@ -672,7 +681,12 @@ int rsa_add_verify_data(struct image_sign_info *info, void *keydest) if (ret) return ret; } - ret = rsa_get_pub_key(info->keydir, info->keyname, e, &pkey); + if (info->keydir && info->keyname) + ret = rsa_get_pub_key(info->keydir, info->keyname, e, &pkey); + else if (info->keyfile) + ret = rsa_get_pub_key(NULL, info->keyfile, e, &pkey); + else + ret = -EINVAL; if (ret) goto err_get_pub_key; #if OPENSSL_VERSION_NUMBER < 0x10100000L || \

On Sun, Jul 18, 2021 at 09:52:03AM -0700, Chan, Donald wrote:
If the 'keyfile' (-G) argument is used, there is little value to require 'keydir' (-k) argument since the public key can also be extracted from the private key itself.
Signed-off-by: Donald Chan hoiho@lab126.com
lib/rsa/rsa-sign.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-)
diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c index f4ed11e74a..f70f352311 100644 --- a/lib/rsa/rsa-sign.c +++ b/lib/rsa/rsa-sign.c @@ -49,16 +49,16 @@ static int rsa_err(const char *msg) }
/**
- rsa_pem_get_pub_key() - read a public key from a .crt file
- rsa_pem_get_pub_key() - read a public key from a private key file or
.crt file
- @keydir: Directory containins the key
- @name Name of key file (will have a .crt extension)
- @keydir: Directory containing the key, can be NULL
- @name Name of key file (will apply a .crt extension if keydir is not
NULL)
- @evpp Returns EVP_PKEY object, or NULL on failure
- @return 0 if ok, -ve on error (in which case *evpp will be set to NULL)
*/ static int rsa_pem_get_pub_key(const char *keydir, const char *name, EVP_PKEY **evpp) {
- char path[1024];
- char path[1024] = {0}; EVP_PKEY *key = NULL; X509 *cert; FILE *f;
@@ -68,7 +68,10 @@ static int rsa_pem_get_pub_key(const char *keydir, const char *name, EVP_PKEY ** return -EINVAL;
*evpp = NULL;
- snprintf(path, sizeof(path), "%s/%s.crt", keydir, name);
- if (keydir && name)
snprintf(path, sizeof(path), "%s/%s.crt", keydir, name);
- else if (name)
f = fopen(path, "r"); if (!f) { fprintf(stderr, "Couldn't open RSA certificate: '%s': %s\n",snprintf(path, sizeof(path), "%s", name);
@@ -76,7 +79,13 @@ static int rsa_pem_get_pub_key(const char *keydir, const char *name, EVP_PKEY ** return -EACCES; }
- /* Read the certificate */
- /* See if it contains a PEM private key? */
- if (PEM_read_PrivateKey(f, evpp, NULL, path)) {
fclose(f);
return 0;
- }
- /* Not a PEM private key, read the certificate */ cert = NULL; if (!PEM_read_X509(f, &cert, NULL, NULL)) { rsa_err("Couldn't read certificate");
@@ -672,7 +681,12 @@ int rsa_add_verify_data(struct image_sign_info *info, void *keydest) if (ret) return ret; }
- ret = rsa_get_pub_key(info->keydir, info->keyname, e, &pkey);
- if (info->keydir && info->keyname)
ret = rsa_get_pub_key(info->keydir, info->keyname, e, &pkey);
- else if (info->keyfile)
ret = rsa_get_pub_key(NULL, info->keyfile, e, &pkey);
- else
if (ret) goto err_get_pub_key;ret = -EINVAL;
#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
This seems reasonable, but the formatting of the patch was destroyed somewhere along the way, can you please resend? Thanks.

If the 'keyfile' (-G) argument is used, there is little value to require 'keydir' (-k) argument since the public key can also be extracted from the private key itself.
Signed-off-by: Donald Chan hoiho@lab126.com --- lib/rsa/rsa-sign.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-)
diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c index f4ed11e74a..f70f352311 100644 --- a/lib/rsa/rsa-sign.c +++ b/lib/rsa/rsa-sign.c @@ -49,16 +49,16 @@ static int rsa_err(const char *msg) }
/** - * rsa_pem_get_pub_key() - read a public key from a .crt file + * rsa_pem_get_pub_key() - read a public key from a private key file or .crt file * - * @keydir: Directory containins the key - * @name Name of key file (will have a .crt extension) + * @keydir: Directory containing the key, can be NULL + * @name Name of key file (will apply a .crt extension if keydir is not NULL) * @evpp Returns EVP_PKEY object, or NULL on failure * @return 0 if ok, -ve on error (in which case *evpp will be set to NULL) */ static int rsa_pem_get_pub_key(const char *keydir, const char *name, EVP_PKEY **evpp) { - char path[1024]; + char path[1024] = {0}; EVP_PKEY *key = NULL; X509 *cert; FILE *f; @@ -68,7 +68,10 @@ static int rsa_pem_get_pub_key(const char *keydir, const char *name, EVP_PKEY ** return -EINVAL;
*evpp = NULL; - snprintf(path, sizeof(path), "%s/%s.crt", keydir, name); + if (keydir && name) + snprintf(path, sizeof(path), "%s/%s.crt", keydir, name); + else if (name) + snprintf(path, sizeof(path), "%s", name); f = fopen(path, "r"); if (!f) { fprintf(stderr, "Couldn't open RSA certificate: '%s': %s\n", @@ -76,7 +79,13 @@ static int rsa_pem_get_pub_key(const char *keydir, const char *name, EVP_PKEY ** return -EACCES; }
- /* Read the certificate */ + /* See if it contains a PEM private key? */ + if (PEM_read_PrivateKey(f, evpp, NULL, path)) { + fclose(f); + return 0; + } + + /* Not a PEM private key, read the certificate */ cert = NULL; if (!PEM_read_X509(f, &cert, NULL, NULL)) { rsa_err("Couldn't read certificate"); @@ -672,7 +681,12 @@ int rsa_add_verify_data(struct image_sign_info *info, void *keydest) if (ret) return ret; } - ret = rsa_get_pub_key(info->keydir, info->keyname, e, &pkey); + if (info->keydir && info->keyname) + ret = rsa_get_pub_key(info->keydir, info->keyname, e, &pkey); + else if (info->keyfile) + ret = rsa_get_pub_key(NULL, info->keyfile, e, &pkey); + else + ret = -EINVAL; if (ret) goto err_get_pub_key; #if OPENSSL_VERSION_NUMBER < 0x10100000L || \

On Wed, Jul 28, 2021 at 08:17:37PM +0000, Chan, Donald wrote:
If the 'keyfile' (-G) argument is used, there is little value to require 'keydir' (-k) argument since the public key can also be extracted from the private key itself.
Signed-off-by: Donald Chan hoiho@lab126.com
lib/rsa/rsa-sign.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-)
This is again corrupted. I think you may need to get git send-email configured to work.

If the 'keyfile' (-G) argument is used, there is little value to require 'keydir' (-k) argument since the public key can also be extracted from the private key itself.
Signed-off-by: Donald Chan hoiho@lab126.com --- lib/rsa/rsa-sign.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-)
diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c index f4ed11e74a..f70f352311 100644 --- a/lib/rsa/rsa-sign.c +++ b/lib/rsa/rsa-sign.c @@ -49,16 +49,16 @@ static int rsa_err(const char *msg) }
/** - * rsa_pem_get_pub_key() - read a public key from a .crt file + * rsa_pem_get_pub_key() - read a public key from a private key file or .crt file * - * @keydir: Directory containins the key - * @name Name of key file (will have a .crt extension) + * @keydir: Directory containing the key, can be NULL + * @name Name of key file (will apply a .crt extension if keydir is not NULL) * @evpp Returns EVP_PKEY object, or NULL on failure * @return 0 if ok, -ve on error (in which case *evpp will be set to NULL) */ static int rsa_pem_get_pub_key(const char *keydir, const char *name, EVP_PKEY **evpp) { - char path[1024]; + char path[1024] = {0}; EVP_PKEY *key = NULL; X509 *cert; FILE *f; @@ -68,7 +68,10 @@ static int rsa_pem_get_pub_key(const char *keydir, const char *name, EVP_PKEY ** return -EINVAL;
*evpp = NULL; - snprintf(path, sizeof(path), "%s/%s.crt", keydir, name); + if (keydir && name) + snprintf(path, sizeof(path), "%s/%s.crt", keydir, name); + else if (name) + snprintf(path, sizeof(path), "%s", name); f = fopen(path, "r"); if (!f) { fprintf(stderr, "Couldn't open RSA certificate: '%s': %s\n", @@ -76,7 +79,13 @@ static int rsa_pem_get_pub_key(const char *keydir, const char *name, EVP_PKEY ** return -EACCES; }
- /* Read the certificate */ + /* See if it contains a PEM private key? */ + if (PEM_read_PrivateKey(f, evpp, NULL, path)) { + fclose(f); + return 0; + } + + /* Not a PEM private key, read the certificate */ cert = NULL; if (!PEM_read_X509(f, &cert, NULL, NULL)) { rsa_err("Couldn't read certificate"); @@ -672,7 +681,12 @@ int rsa_add_verify_data(struct image_sign_info *info, void *keydest) if (ret) return ret; } - ret = rsa_get_pub_key(info->keydir, info->keyname, e, &pkey); + if (info->keydir && info->keyname) + ret = rsa_get_pub_key(info->keydir, info->keyname, e, &pkey); + else if (info->keyfile) + ret = rsa_get_pub_key(NULL, info->keyfile, e, &pkey); + else + ret = -EINVAL; if (ret) goto err_get_pub_key; #if OPENSSL_VERSION_NUMBER < 0x10100000L || \

Hi Donald,
On Wed, 28 Jul 2021 at 18:35, Donald Chan hoiho@lab126.com wrote:
If the 'keyfile' (-G) argument is used, there is little value to require 'keydir' (-k) argument since the public key can also be extracted from the private key itself.
Signed-off-by: Donald Chan hoiho@lab126.com
lib/rsa/rsa-sign.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-)
diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c index f4ed11e74a..f70f352311 100644 --- a/lib/rsa/rsa-sign.c +++ b/lib/rsa/rsa-sign.c @@ -49,16 +49,16 @@ static int rsa_err(const char *msg) }
/**
- rsa_pem_get_pub_key() - read a public key from a .crt file
- rsa_pem_get_pub_key() - read a public key from a private key file or .crt file
- @keydir: Directory containins the key
- @name Name of key file (will have a .crt extension)
- @keydir: Directory containing the key, can be NULL
*/
- @name Name of key file (will apply a .crt extension if keydir is not NULL)
- @evpp Returns EVP_PKEY object, or NULL on failure
- @return 0 if ok, -ve on error (in which case *evpp will be set to NULL)
static int rsa_pem_get_pub_key(const char *keydir, const char *name, EVP_PKEY **evpp) {
char path[1024];
char path[1024] = {0}; EVP_PKEY *key = NULL; X509 *cert; FILE *f;
@@ -68,7 +68,10 @@ static int rsa_pem_get_pub_key(const char *keydir, const char *name, EVP_PKEY ** return -EINVAL;
*evpp = NULL;
snprintf(path, sizeof(path), "%s/%s.crt", keydir, name);
if (keydir && name)
snprintf(path, sizeof(path), "%s/%s.crt", keydir, name);
else if (name)
snprintf(path, sizeof(path), "%s", name); f = fopen(path, "r"); if (!f) { fprintf(stderr, "Couldn't open RSA certificate: '%s': %s\n",
@@ -76,7 +79,13 @@ static int rsa_pem_get_pub_key(const char *keydir, const char *name, EVP_PKEY ** return -EACCES; }
/* Read the certificate */
/* See if it contains a PEM private key? */
if (PEM_read_PrivateKey(f, evpp, NULL, path)) {
fclose(f);
return 0;
}
/* Not a PEM private key, read the certificate */ cert = NULL; if (!PEM_read_X509(f, &cert, NULL, NULL)) { rsa_err("Couldn't read certificate");
@@ -672,7 +681,12 @@ int rsa_add_verify_data(struct image_sign_info *info, void *keydest) if (ret) return ret; }
ret = rsa_get_pub_key(info->keydir, info->keyname, e, &pkey);
if (info->keydir && info->keyname)
ret = rsa_get_pub_key(info->keydir, info->keyname, e, &pkey);
else if (info->keyfile)
ret = rsa_get_pub_key(NULL, info->keyfile, e, &pkey);
else
ret = -EINVAL; if (ret) goto err_get_pub_key;
#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
2.16.6
Can we work this into a test somehow? The normal test is test_vboot.py - you could modify that or add a new test into that file perhaps?
Regards, Simon

Hi Simon,
On 31 Jul 2021, at 9:59, Simon Glass wrote:
CAUTION: This email originated from outside of the organization. Do not click links or open attachments unless you can confirm the sender and know the content is safe.
Hi Donald,
On Wed, 28 Jul 2021 at 18:35, Donald Chan hoiho@lab126.com wrote:
If the 'keyfile' (-G) argument is used, there is little value to require 'keydir' (-k) argument since the public key can also be extracted from the private key itself.
Signed-off-by: Donald Chan hoiho@lab126.com
lib/rsa/rsa-sign.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-)
diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c index f4ed11e74a..f70f352311 100644 --- a/lib/rsa/rsa-sign.c +++ b/lib/rsa/rsa-sign.c @@ -49,16 +49,16 @@ static int rsa_err(const char *msg) }
/**
- rsa_pem_get_pub_key() - read a public key from a .crt file
- rsa_pem_get_pub_key() - read a public key from a private key file
or .crt file
- @keydir: Directory containins the key
- @name Name of key file (will have a .crt extension)
- @keydir: Directory containing the key, can be NULL
- @name Name of key file (will apply a .crt extension if
keydir is not NULL)
- @evpp Returns EVP_PKEY object, or NULL on failure
- @return 0 if ok, -ve on error (in which case *evpp will be set to
NULL) */ static int rsa_pem_get_pub_key(const char *keydir, const char *name, EVP_PKEY **evpp) {
char path[1024];
char path[1024] = {0}; EVP_PKEY *key = NULL; X509 *cert; FILE *f;
@@ -68,7 +68,10 @@ static int rsa_pem_get_pub_key(const char *keydir, const char *name, EVP_PKEY ** return -EINVAL;
*evpp = NULL;
snprintf(path, sizeof(path), "%s/%s.crt", keydir, name);
if (keydir && name)
snprintf(path, sizeof(path), "%s/%s.crt", keydir,
name);
else if (name)
snprintf(path, sizeof(path), "%s", name); f = fopen(path, "r"); if (!f) { fprintf(stderr, "Couldn't open RSA certificate: '%s':
%s\n", @@ -76,7 +79,13 @@ static int rsa_pem_get_pub_key(const char *keydir, const char *name, EVP_PKEY ** return -EACCES; }
/* Read the certificate */
/* See if it contains a PEM private key? */
if (PEM_read_PrivateKey(f, evpp, NULL, path)) {
fclose(f);
return 0;
}
/* Not a PEM private key, read the certificate */ cert = NULL; if (!PEM_read_X509(f, &cert, NULL, NULL)) { rsa_err("Couldn't read certificate");
@@ -672,7 +681,12 @@ int rsa_add_verify_data(struct image_sign_info *info, void *keydest) if (ret) return ret; }
ret = rsa_get_pub_key(info->keydir, info->keyname, e, &pkey);
if (info->keydir && info->keyname)
ret = rsa_get_pub_key(info->keydir, info->keyname, e,
&pkey);
else if (info->keyfile)
ret = rsa_get_pub_key(NULL, info->keyfile, e, &pkey);
else
ret = -EINVAL; if (ret) goto err_get_pub_key;
#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
2.16.6
Can we work this into a test somehow? The normal test is test_vboot.py
- you could modify that or add a new test into that file perhaps?
Sure, let me work on this and submit a new patch.
Thanks Donald

On Wed, Jul 28, 2021 at 05:34:41PM -0700, Donald Chan wrote:
If the 'keyfile' (-G) argument is used, there is little value to require 'keydir' (-k) argument since the public key can also be extracted from the private key itself.
Signed-off-by: Donald Chan hoiho@lab126.com
This breaks the "vboot" tests run under sandbox, please investigate and fix, thanks!
participants (5)
-
Chan, Donald
-
Chan, Donald
-
Donald Chan
-
Simon Glass
-
Tom Rini