]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
PROV: Implement PEM to DER deserializer
authorRichard Levitte <levitte@openssl.org>
Thu, 9 Jul 2020 17:09:40 +0000 (19:09 +0200)
committerRichard Levitte <levitte@openssl.org>
Fri, 24 Jul 2020 14:35:10 +0000 (16:35 +0200)
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/12410)

providers/defltprov.c
providers/implementations/include/prov/implementations.h
providers/implementations/serializers/build.info
providers/implementations/serializers/deserialize_common.c
providers/implementations/serializers/deserialize_pem2der.c [new file with mode: 0644]
providers/implementations/serializers/serializer_local.h

index 7d8681bb16d26745badbd5ffa54d62c755a7fbae..7ab006ae831ae36b3dfa4d1ef1c2ecf96915830c 100644 (file)
@@ -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 }
 };
 
index 07452a372e97e4540c5652ebed2d33b5b91c92b4..4890f11969112a11bf47319b57d44b5cd1f20a53 100644 (file)
@@ -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[];
index 5eaa1683641eb0dba0ceae05c54e5b0686a9b130..bcfe9d4d4ba9ba3173f5015b7b98d9969aa158f1 100644 (file)
@@ -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
 
index 17362f2270c17b19fdf08a1a539d6e86fc0fb02f..ba8aa6d6d644a789a1b9470e406beecff1157290 100644 (file)
@@ -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 (file)
index 0000000..53dd317
--- /dev/null
@@ -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 }
+};
index 3d16320938183ecb9f6978271cab2db42c2c04f5..adabf6a6b3252e7e86d2df84141726358d08f2d5 100644 (file)
@@ -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);