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); | ||||||
|         if (a != NULL && (bak_a = *a) != NULL) |     ERR_pop_to_mark(); | ||||||
|             ppkey = a; |     if (p8info != NULL) { | ||||||
|         dctx = OSSL_DECODER_CTX_new_for_pkey(ppkey, "DER", |         if (key_name == NULL | ||||||
|                                              input_structures[i], key_name, |                 && PKCS8_pkey_get0(&algoid, NULL, NULL, NULL, p8info) | ||||||
|                                              EVP_PKEY_KEYPAIR, libctx, propq); |                 && OBJ_obj2txt(keytypebuf, sizeof(keytypebuf), algoid, 0)) | ||||||
|         if (a != NULL) |             key_name = keytypebuf; | ||||||
|             *a = bak_a; |         structure = "PrivateKeyInfo"; | ||||||
|         if (dctx == NULL) |         PKCS8_PRIV_KEY_INFO_free(p8info); | ||||||
|             continue; |     } else { | ||||||
| 
 |         structure = "type-specific"; | ||||||
|         ret = OSSL_DECODER_from_data(dctx, pp, &len); |  | ||||||
|         OSSL_DECODER_CTX_free(dctx); |  | ||||||
|         if (ret) { |  | ||||||
|             if (*ppkey != NULL |  | ||||||
|                 && evp_keymgmt_util_has(*ppkey, OSSL_KEYMGMT_SELECT_PRIVATE_KEY)) { |  | ||||||
|                 if (a != NULL) |  | ||||||
|                     *a = *ppkey; |  | ||||||
|                 return *ppkey; |  | ||||||
|             } |  | ||||||
|             *pp = p; |  | ||||||
|             goto err; |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|     /* Fall through to error if all decodes failed */ |     *pp = p; | ||||||
| err: | 
 | ||||||
|  |     if (a != NULL && (bak_a = *a) != NULL) | ||||||
|  |         ppkey = a; | ||||||
|  |     dctx = OSSL_DECODER_CTX_new_for_pkey(ppkey, "DER", structure, key_name, | ||||||
|  |                                          EVP_PKEY_KEYPAIR, libctx, propq); | ||||||
|  |     if (a != NULL) | ||||||
|  |         *a = bak_a; | ||||||
|  |     if (dctx == NULL) | ||||||
|  |         goto err; | ||||||
|  | 
 | ||||||
|  |     ret = OSSL_DECODER_from_data(dctx, pp, &len); | ||||||
|  |     OSSL_DECODER_CTX_free(dctx); | ||||||
|  |     if (ret | ||||||
|  |         && *ppkey != NULL | ||||||
|  |         && evp_keymgmt_util_has(*ppkey, OSSL_KEYMGMT_SELECT_PRIVATE_KEY)) { | ||||||
|  |         if (a != NULL) | ||||||
|  |             *a = *ppkey; | ||||||
|  |         return *ppkey; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |  err: | ||||||
|     if (ppkey != a) |     if (ppkey != a) | ||||||
|         EVP_PKEY_free(*ppkey); |         EVP_PKEY_free(*ppkey); | ||||||
|     return NULL; |     return NULL; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue