mirror of https://github.com/openssl/openssl.git
				
				
				
			Improve the performance of d2i_AutoPrivateKey and friends
Probe first to see if we have a PKCS8 file to improve decoder performance.
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
(Merged from https://github.com/openssl/openssl/pull/20416)
(cherry picked from commit dba97d4c71)
			
			
This commit is contained in:
		
							parent
							
								
									f0ea7a51aa
								
							
						
					
					
						commit
						fe24a06cfa
					
				| 
						 | 
					@ -22,6 +22,7 @@
 | 
				
			||||||
#include "crypto/asn1.h"
 | 
					#include "crypto/asn1.h"
 | 
				
			||||||
#include "crypto/evp.h"
 | 
					#include "crypto/evp.h"
 | 
				
			||||||
#include "internal/asn1.h"
 | 
					#include "internal/asn1.h"
 | 
				
			||||||
 | 
					#include "internal/sizes.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static EVP_PKEY *
 | 
					static EVP_PKEY *
 | 
				
			||||||
d2i_PrivateKey_decoder(int keytype, EVP_PKEY **a, const unsigned char **pp,
 | 
					d2i_PrivateKey_decoder(int keytype, EVP_PKEY **a, const unsigned char **pp,
 | 
				
			||||||
| 
						 | 
					@ -32,8 +33,12 @@ d2i_PrivateKey_decoder(int keytype, EVP_PKEY **a, const unsigned char **pp,
 | 
				
			||||||
    EVP_PKEY *pkey = NULL, *bak_a = NULL;
 | 
					    EVP_PKEY *pkey = NULL, *bak_a = NULL;
 | 
				
			||||||
    EVP_PKEY **ppkey = &pkey;
 | 
					    EVP_PKEY **ppkey = &pkey;
 | 
				
			||||||
    const char *key_name = NULL;
 | 
					    const char *key_name = NULL;
 | 
				
			||||||
    const char *input_structures[] = { "type-specific", "PrivateKeyInfo", NULL };
 | 
					    char keytypebuf[OSSL_MAX_NAME_SIZE];
 | 
				
			||||||
    int i, ret;
 | 
					    int ret;
 | 
				
			||||||
 | 
					    const unsigned char *p = *pp;
 | 
				
			||||||
 | 
					    const char *structure;
 | 
				
			||||||
 | 
					    PKCS8_PRIV_KEY_INFO *p8info;
 | 
				
			||||||
 | 
					    const ASN1_OBJECT *algoid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (keytype != EVP_PKEY_NONE) {
 | 
					    if (keytype != EVP_PKEY_NONE) {
 | 
				
			||||||
        key_name = evp_pkey_type2name(keytype);
 | 
					        key_name = evp_pkey_type2name(keytype);
 | 
				
			||||||
| 
						 | 
					@ -41,34 +46,42 @@ d2i_PrivateKey_decoder(int keytype, EVP_PKEY **a, const unsigned char **pp,
 | 
				
			||||||
            return NULL;
 | 
					            return NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (i = 0;  i < (int)OSSL_NELEM(input_structures); ++i) {
 | 
					    /* This is just a probe. It might fail, so we ignore errors */
 | 
				
			||||||
        const unsigned char *p = *pp;
 | 
					    ERR_set_mark();
 | 
				
			||||||
 | 
					    p8info = d2i_PKCS8_PRIV_KEY_INFO(NULL, pp, len);
 | 
				
			||||||
 | 
					    ERR_pop_to_mark();
 | 
				
			||||||
 | 
					    if (p8info != NULL) {
 | 
				
			||||||
 | 
					        if (key_name == NULL
 | 
				
			||||||
 | 
					                && PKCS8_pkey_get0(&algoid, NULL, NULL, NULL, p8info)
 | 
				
			||||||
 | 
					                && OBJ_obj2txt(keytypebuf, sizeof(keytypebuf), algoid, 0))
 | 
				
			||||||
 | 
					            key_name = keytypebuf;
 | 
				
			||||||
 | 
					        structure = "PrivateKeyInfo";
 | 
				
			||||||
 | 
					        PKCS8_PRIV_KEY_INFO_free(p8info);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        structure = "type-specific";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    *pp = p;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (a != NULL && (bak_a = *a) != NULL)
 | 
					    if (a != NULL && (bak_a = *a) != NULL)
 | 
				
			||||||
        ppkey = a;
 | 
					        ppkey = a;
 | 
				
			||||||
        dctx = OSSL_DECODER_CTX_new_for_pkey(ppkey, "DER",
 | 
					    dctx = OSSL_DECODER_CTX_new_for_pkey(ppkey, "DER", structure, key_name,
 | 
				
			||||||
                                             input_structures[i], key_name,
 | 
					 | 
				
			||||||
                                         EVP_PKEY_KEYPAIR, libctx, propq);
 | 
					                                         EVP_PKEY_KEYPAIR, libctx, propq);
 | 
				
			||||||
    if (a != NULL)
 | 
					    if (a != NULL)
 | 
				
			||||||
        *a = bak_a;
 | 
					        *a = bak_a;
 | 
				
			||||||
    if (dctx == NULL)
 | 
					    if (dctx == NULL)
 | 
				
			||||||
            continue;
 | 
					        goto err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ret = OSSL_DECODER_from_data(dctx, pp, &len);
 | 
					    ret = OSSL_DECODER_from_data(dctx, pp, &len);
 | 
				
			||||||
    OSSL_DECODER_CTX_free(dctx);
 | 
					    OSSL_DECODER_CTX_free(dctx);
 | 
				
			||||||
        if (ret) {
 | 
					    if (ret
 | 
				
			||||||
            if (*ppkey != NULL
 | 
					        && *ppkey != NULL
 | 
				
			||||||
        && evp_keymgmt_util_has(*ppkey, OSSL_KEYMGMT_SELECT_PRIVATE_KEY)) {
 | 
					        && evp_keymgmt_util_has(*ppkey, OSSL_KEYMGMT_SELECT_PRIVATE_KEY)) {
 | 
				
			||||||
        if (a != NULL)
 | 
					        if (a != NULL)
 | 
				
			||||||
            *a = *ppkey;
 | 
					            *a = *ppkey;
 | 
				
			||||||
        return *ppkey;
 | 
					        return *ppkey;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
            *pp = p;
 | 
					
 | 
				
			||||||
            goto err;
 | 
					 err:
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    /* Fall through to error if all decodes failed */
 | 
					 | 
				
			||||||
err:
 | 
					 | 
				
			||||||
    if (ppkey != a)
 | 
					    if (ppkey != a)
 | 
				
			||||||
        EVP_PKEY_free(*ppkey);
 | 
					        EVP_PKEY_free(*ppkey);
 | 
				
			||||||
    return NULL;
 | 
					    return NULL;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue