-
-
Save levitte/7a27cebdb9537ff0a59641c9a5bed53d to your computer and use it in GitHub Desktop.
About openssl/openssl#20657
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <openssl/evp.h> | |
| #include <openssl/err.h> | |
| #include <openssl/pem.h> | |
| #include <openssl/bio.h> | |
| #include <openssl/provider.h> | |
| /* BEGIN COPY */ | |
| /* The following is extracted from https://github.com/junaruga/openssl/raw/41bc792df2cf54660264bd6fc6368044f2877e99/ext/openssl/ossl_pkey.c and modified to get rid of Ruby specific stuff */ | |
| # include <openssl/decoder.h> | |
| EVP_PKEY * | |
| ossl_pkey_read_generic(BIO *bio, char *pass) | |
| { | |
| OSSL_DECODER_CTX *dctx; | |
| EVP_PKEY *pkey = NULL; | |
| int pos = 0, pos2; | |
| dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "DER", NULL, NULL, 0, NULL, NULL); | |
| if (!dctx) | |
| goto out; | |
| if (OSSL_DECODER_CTX_set_pem_password_cb(dctx, PEM_def_callback, pass) != 1) | |
| goto out; | |
| /* First check DER */ | |
| fprintf(stderr, "[DEBUG] Calling OSSL_DECODER_from_bio 1.\n"); | |
| if (OSSL_DECODER_from_bio(dctx, bio) == 1) | |
| goto out; | |
| ERR_print_errors_fp(stderr); | |
| BIO_reset(bio); | |
| /* Then check PEM; multiple OSSL_DECODER_from_bio() calls may be needed */ | |
| if (OSSL_DECODER_CTX_set_input_type(dctx, "PEM") != 1) | |
| goto out; | |
| /* | |
| * First check for private key formats. This is to keep compatibility with | |
| * ruby/openssl < 3.0 which decoded the following as a private key. | |
| * | |
| * $ openssl ecparam -name prime256v1 -genkey -outform PEM | |
| * -----BEGIN EC PARAMETERS----- | |
| * BggqhkjOPQMBBw== | |
| * -----END EC PARAMETERS----- | |
| * -----BEGIN EC PRIVATE KEY----- | |
| * MHcCAQEEIAG8ugBbA5MHkqnZ9ujQF93OyUfL9tk8sxqM5Wv5tKg5oAoGCCqGSM49 | |
| * AwEHoUQDQgAEVcjhJfkwqh5C7kGuhAf8XaAjVuG5ADwb5ayg/cJijCgs+GcXeedj | |
| * 86avKpGH84DXUlB23C/kPt+6fXYlitUmXQ== | |
| * -----END EC PRIVATE KEY----- | |
| * | |
| * While the first PEM block is a proper encoding of ECParameters, thus | |
| * OSSL_DECODER_from_bio() would pick it up, ruby/openssl used to return | |
| * the latter instead. Existing applications expect this behavior. | |
| * | |
| * Note that normally, the input is supposed to contain a single decodable | |
| * PEM block only, so this special handling should not create a new problem. | |
| */ | |
| OSSL_DECODER_CTX_set_selection(dctx, EVP_PKEY_KEYPAIR); | |
| while (1) { | |
| fprintf(stderr, "[DEBUG] Calling OSSL_DECODER_from_bio 2.\n"); | |
| if (OSSL_DECODER_from_bio(dctx, bio) == 1) | |
| goto out; | |
| ERR_print_errors_fp(stderr); | |
| if (BIO_eof(bio)) | |
| break; | |
| pos2 = BIO_tell(bio); | |
| if (pos2 < 0 || pos2 <= pos) | |
| break; | |
| ERR_clear_error(); /* Maybe print? */ | |
| pos = pos2; | |
| } | |
| BIO_reset(bio); | |
| OSSL_DECODER_CTX_set_selection(dctx, 0); | |
| while (1) { | |
| fprintf(stderr, "[DEBUG] Calling OSSL_DECODER_from_bio 3.\n"); | |
| if (OSSL_DECODER_from_bio(dctx, bio) == 1) | |
| goto out; | |
| ERR_print_errors_fp(stderr); | |
| if (BIO_eof(bio)) | |
| break; | |
| pos2 = BIO_tell(bio); | |
| if (pos2 < 0 || pos2 <= pos) | |
| break; | |
| ERR_clear_error(); /* Maybe print? */ | |
| pos = pos2; | |
| } | |
| out: | |
| OSSL_DECODER_CTX_free(dctx); | |
| return pkey; | |
| } | |
| /* | |
| * call-seq: | |
| * OpenSSL::PKey.read(string [, pwd ]) -> PKey | |
| * OpenSSL::PKey.read(io [, pwd ]) -> PKey | |
| * | |
| * Reads a DER or PEM encoded string from _string_ or _io_ and returns an | |
| * instance of the appropriate PKey class. | |
| * | |
| * === Parameters | |
| * * _string_ is a DER- or PEM-encoded string containing an arbitrary private | |
| * or public key. | |
| * * _io_ is an instance of IO containing a DER- or PEM-encoded | |
| * arbitrary private or public key. | |
| * * _pwd_ is an optional password in case _string_ or _io_ is an encrypted | |
| * PEM resource. | |
| */ | |
| static EVP_PKEY * | |
| ossl_pkey_new_from_data(char *data, char *pass) | |
| { | |
| EVP_PKEY *pkey; | |
| BIO *bio; | |
| bio = BIO_new_mem_buf(data, strlen(data)); | |
| if (!bio) { | |
| ERR_raise_data(ERR_LIB_NONE, ERR_R_BIO_LIB, | |
| "BIO_new_mem_buf() failed"); | |
| return NULL; | |
| } | |
| fprintf(stderr, "[DEBUG] Calling ossl_pkey_read_generic from ossl_pkey_new_from_data.\n"); | |
| pkey = ossl_pkey_read_generic(bio, pass); | |
| BIO_free(bio); | |
| if (!pkey) | |
| ERR_raise_data(ERR_LIB_NONE, 0, "Could not parse PKey"); | |
| return pkey; | |
| } | |
| /* END COPY */ | |
| static int print_provider(OSSL_PROVIDER *prov, void *unused) | |
| { | |
| printf(" %s\n", OSSL_PROVIDER_get0_name(prov)); | |
| return 1; | |
| } | |
| int main(int argc, char *argv[]) | |
| { | |
| static char data[1024 * 1024]; | |
| EVP_PKEY *pkey; | |
| printf("Loaded providers:\n"); | |
| OSSL_PROVIDER_do_all(NULL, &print_provider, NULL); | |
| /* Slurp */ | |
| FILE *f; | |
| size_t data_size; | |
| if ((f = fopen(argv[1], "r")) == NULL | |
| || (data_size = fread(data, 1, sizeof(data), f)) == 0) { | |
| if (f) | |
| fclose(f); | |
| ERR_raise_data(ERR_LIB_NONE, 0, "Could not read PKey"); | |
| } else { | |
| fclose(f); | |
| data[data_size] = '\0'; | |
| pkey = ossl_pkey_new_from_data(data, ""); | |
| if (pkey) { | |
| printf("Got a pkey! %p\n", (void *)pkey); | |
| printf("It's held by the provider %s\n", | |
| OSSL_PROVIDER_get0_name(EVP_PKEY_get0_provider(pkey))); | |
| } | |
| EVP_PKEY_free(pkey); | |
| } | |
| ERR_print_errors_fp(stderr); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| config_diagnostics = 1 | |
| openssl_conf = openssl_init | |
| .include fipsmodule.cnf | |
| [openssl_init] | |
| providers = provider_sect | |
| alg_section = algorithm_sect | |
| [provider_sect] | |
| fips = fips_sect | |
| base = base_sect | |
| [base_sect] | |
| activate = 1 | |
| [fips_sect] | |
| activate = 1 | |
| [algorithm_sect] | |
| default_properties = fips=yes |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| $ cc -o 20657 20657.c -lcrypto | |
| $ OPENSSL_CONF=./20657.cnf OPENSSL_CONF_INCLUDE=/home/levitte/.local/opt/openssl-3.0/ssl OPENSSL_MODULES=/home/levitte/.local/opt/openssl-3.0/lib/ossl-modules ./20657 key.pem | |
| Loaded providers: | |
| fips | |
| base | |
| [DEBUG] Calling ossl_pkey_read_generic from ossl_pkey_new_from_data. | |
| [DEBUG] Calling OSSL_DECODER_from_bio 1. | |
| 4037CD68247F0000:error:1E08010C:DECODER routines:OSSL_DECODER_from_bio:unsupported:../crypto/encode_decode/decoder_lib.c:101:No supported data to decode. Input type: DER | |
| [DEBUG] Calling OSSL_DECODER_from_bio 2. | |
| [DEBUG] Calling OSSL_DECODER_from_bio 3. | |
| 4037CD68247F0000:error:00800000:unknown library:ossl_pkey_new_from_data:unknown library:20657.c:125:Could not parse PKey | |
| $ ./20657 key.pem | |
| Loaded providers: | |
| default | |
| [DEBUG] Calling ossl_pkey_read_generic from ossl_pkey_new_from_data. | |
| [DEBUG] Calling OSSL_DECODER_from_bio 1. | |
| 4057F815847F0000:error:1E08010C:DECODER routines:OSSL_DECODER_from_bio:unsupported:../crypto/encode_decode/decoder_lib.c:101:No supported data to decode. Input type: DER | |
| [DEBUG] Calling OSSL_DECODER_from_bio 2. | |
| Got a pkey! 0x5601c5d77030 | |
| It's held by the provider default |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment