diff options
author | Richard Levitte <levitte@openssl.org> | 2020-07-09 19:09:40 +0200 |
---|---|---|
committer | Richard Levitte <levitte@openssl.org> | 2020-07-24 16:35:10 +0200 |
commit | dcfacbbfe9b3f8fa13eeb17a8fa4c89edefc8389 (patch) | |
tree | 0b202a14254f2d444995c0ae9da3ce38903057d4 | |
parent | 1017b8e4a161682c909a98ebf3f7a21b38d6c677 (diff) |
PROV: Implement PEM to DER deserializer
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/12410)
6 files changed, 142 insertions, 1 deletions
diff --git a/providers/defltprov.c b/providers/defltprov.c index 7d8681bb16..7ab006ae83 100644 --- a/providers/defltprov.c +++ b/providers/defltprov.c @@ -538,6 +538,9 @@ static const OSSL_ALGORITHM deflt_deserializer[] = { { "RSA", "provider=default,fips=yes,input=der", der_to_rsa_deserializer_functions }, + { "DER", "provider=default,fips=yes,input=pem", + pem_to_der_deserializer_functions }, + { NULL, NULL, NULL } }; diff --git a/providers/implementations/include/prov/implementations.h b/providers/implementations/include/prov/implementations.h index 07452a372e..4890f11969 100644 --- a/providers/implementations/include/prov/implementations.h +++ b/providers/implementations/include/prov/implementations.h @@ -360,3 +360,4 @@ extern const OSSL_DISPATCH ec_pub_pem_serializer_functions[]; extern const OSSL_DISPATCH ec_param_pem_serializer_functions[]; extern const OSSL_DISPATCH der_to_rsa_deserializer_functions[]; +extern const OSSL_DISPATCH pem_to_der_deserializer_functions[]; diff --git a/providers/implementations/serializers/build.info b/providers/implementations/serializers/build.info index 5eaa168364..bcfe9d4d4b 100644 --- a/providers/implementations/serializers/build.info +++ b/providers/implementations/serializers/build.info @@ -11,7 +11,7 @@ $EC_GOAL=../../libimplementations.a SOURCE[$SERIALIZER_GOAL]=serializer_common.c deserialize_common.c -SOURCE[$RSA_GOAL]=deserialize_der2rsa.c +SOURCE[$RSA_GOAL]=deserialize_der2rsa.c deserialize_pem2der.c SOURCE[$RSA_GOAL]=serializer_rsa.c serializer_rsa_priv.c serializer_rsa_pub.c DEPEND[serializer_rsa.o]=../../common/include/prov/der_rsa.h diff --git a/providers/implementations/serializers/deserialize_common.c b/providers/implementations/serializers/deserialize_common.c index 17362f2270..ba8aa6d6d6 100644 --- a/providers/implementations/serializers/deserialize_common.c +++ b/providers/implementations/serializers/deserialize_common.c @@ -29,3 +29,14 @@ int ossl_prov_read_der(PROV_CTX *provctx, OSSL_CORE_BIO *cin, BIO_free(in); return ok; } + +int ossl_prov_read_pem(PROV_CTX *provctx, OSSL_CORE_BIO *cin, + char **pem_name, char **pem_header, + unsigned char **data, long *len) +{ + BIO *in = bio_new_from_core_bio(provctx, cin); + int ok = (PEM_read_bio(in, pem_name, pem_header, data, len) > 0); + + BIO_free(in); + return ok; +} diff --git a/providers/implementations/serializers/deserialize_pem2der.c b/providers/implementations/serializers/deserialize_pem2der.c new file mode 100644 index 0000000000..53dd317bf4 --- /dev/null +++ b/providers/implementations/serializers/deserialize_pem2der.c @@ -0,0 +1,123 @@ +/* + * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * RSA low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + +#include <openssl/core_dispatch.h> +#include <openssl/core_names.h> +#include <openssl/crypto.h> +#include <openssl/params.h> +#include <openssl/pem.h> +#include "prov/bio.h" +#include "prov/implementations.h" +#include "serializer_local.h" + +static OSSL_FUNC_deserializer_newctx_fn pem2der_newctx; +static OSSL_FUNC_deserializer_freectx_fn pem2der_freectx; +static OSSL_FUNC_deserializer_gettable_params_fn pem2der_gettable_params; +static OSSL_FUNC_deserializer_get_params_fn pem2der_get_params; +static OSSL_FUNC_deserializer_deserialize_fn pem2der_deserialize; + +static void *pem2der_newctx(void *provctx) +{ + return provctx; +} + +static void pem2der_freectx(void *vctx) +{ +} + +static const OSSL_PARAM *pem2der_gettable_params(void) +{ + static const OSSL_PARAM gettables[] = { + { OSSL_DESERIALIZER_PARAM_INPUT_TYPE, OSSL_PARAM_UTF8_PTR, NULL, 0, 0 }, + OSSL_PARAM_END, + }; + + return gettables; +} + +static int pem2der_get_params(OSSL_PARAM params[]) +{ + OSSL_PARAM *p; + + p = OSSL_PARAM_locate(params, OSSL_DESERIALIZER_PARAM_INPUT_TYPE); + if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, "PEM")) + return 0; + + return 1; +} + +static int pem2der_deserialize(void *vctx, OSSL_CORE_BIO *cin, + OSSL_CALLBACK *data_cb, void *data_cbarg, + OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) +{ + PROV_CTX *ctx = vctx; + char *pem_name = NULL, *pem_header = NULL; + unsigned char *der = NULL; + long der_len = 0; + int ok = 0; + + if (ossl_prov_read_pem(ctx, cin, &pem_name, &pem_header, + &der, &der_len) <= 0) + return 0; + +#if 0 /* PEM decryption coming soon */ + /* + * 10 is the number of characters in "Proc-Type:", which + * PEM_get_EVP_CIPHER_INFO() requires to be present. + * If the PEM header has less characters than that, it's + * not worth spending cycles on it. + */ + if (strlen(*pem_header) > 10) { + EVP_CIPHER_INFO cipher; + struct pem_pass_data pass_data; + + if (!PEM_get_EVP_CIPHER_INFO(*pem_header, &cipher) + || !file_fill_pem_pass_data(&pass_data, "PEM pass phrase", uri, + ui_method, ui_data) + || !PEM_do_header(&cipher, *data, len, file_get_pem_pass, + &pass_data)) + goto end; + } +#endif + + { + OSSL_PARAM params[3]; + + params[0] = + OSSL_PARAM_construct_utf8_string(OSSL_DESERIALIZER_PARAM_DATA_TYPE, + pem_name, 0); + params[1] = + OSSL_PARAM_construct_octet_string(OSSL_DESERIALIZER_PARAM_DATA, + der, der_len); + params[2] = OSSL_PARAM_construct_end(); + + ok = data_cb(params, data_cbarg); + } + + OPENSSL_free(pem_name); + OPENSSL_free(pem_header); + OPENSSL_free(der); + return ok; +} + +const OSSL_DISPATCH pem_to_der_deserializer_functions[] = { + { OSSL_FUNC_DESERIALIZER_NEWCTX, (void (*)(void))pem2der_newctx }, + { OSSL_FUNC_DESERIALIZER_FREECTX, (void (*)(void))pem2der_freectx }, + { OSSL_FUNC_DESERIALIZER_GETTABLE_PARAMS, + (void (*)(void))pem2der_gettable_params }, + { OSSL_FUNC_DESERIALIZER_GET_PARAMS, (void (*)(void))pem2der_get_params }, + { OSSL_FUNC_DESERIALIZER_DESERIALIZE, (void (*)(void))pem2der_deserialize }, + { 0, NULL } +}; diff --git a/providers/implementations/serializers/serializer_local.h b/providers/implementations/serializers/serializer_local.h index 3d16320938..adabf6a6b3 100644 --- a/providers/implementations/serializers/serializer_local.h +++ b/providers/implementations/serializers/serializer_local.h @@ -162,3 +162,6 @@ int ossl_prov_write_pub_pem_from_obj(BIO *out, const void *obj, int obj_nid, int ossl_prov_read_der(PROV_CTX *provctx, OSSL_CORE_BIO *cin, unsigned char **data, long *len); +int ossl_prov_read_pem(PROV_CTX *provctx, OSSL_CORE_BIO *cin, + char **pem_name, char **pem_header, + unsigned char **data, long *len); |