1/*
2 * Copyright 2001-2023 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License").  You may not use
5 * this file except in compliance with the License.  You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10/* We need to use some engine deprecated APIs */
11#define OPENSSL_SUPPRESS_DEPRECATED
12
13#include "eng_local.h"
14
15/* Basic get/set stuff */
16
17int ENGINE_set_load_privkey_function(ENGINE *e,
18                                     ENGINE_LOAD_KEY_PTR loadpriv_f)
19{
20    e->load_privkey = loadpriv_f;
21    return 1;
22}
23
24int ENGINE_set_load_pubkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpub_f)
25{
26    e->load_pubkey = loadpub_f;
27    return 1;
28}
29
30int ENGINE_set_load_ssl_client_cert_function(ENGINE *e,
31                                             ENGINE_SSL_CLIENT_CERT_PTR
32                                             loadssl_f)
33{
34    e->load_ssl_client_cert = loadssl_f;
35    return 1;
36}
37
38ENGINE_LOAD_KEY_PTR ENGINE_get_load_privkey_function(const ENGINE *e)
39{
40    return e->load_privkey;
41}
42
43ENGINE_LOAD_KEY_PTR ENGINE_get_load_pubkey_function(const ENGINE *e)
44{
45    return e->load_pubkey;
46}
47
48ENGINE_SSL_CLIENT_CERT_PTR ENGINE_get_ssl_client_cert_function(const ENGINE
49                                                               *e)
50{
51    return e->load_ssl_client_cert;
52}
53
54/* API functions to load public/private keys */
55
56EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id,
57                                  UI_METHOD *ui_method, void *callback_data)
58{
59    EVP_PKEY *pkey;
60
61    if (e == NULL) {
62        ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
63        return NULL;
64    }
65    if (!CRYPTO_THREAD_write_lock(global_engine_lock))
66        return NULL;
67    if (e->funct_ref == 0) {
68        CRYPTO_THREAD_unlock(global_engine_lock);
69        ERR_raise(ERR_LIB_ENGINE, ENGINE_R_NOT_INITIALISED);
70        return NULL;
71    }
72    CRYPTO_THREAD_unlock(global_engine_lock);
73    if (!e->load_privkey) {
74        ERR_raise(ERR_LIB_ENGINE, ENGINE_R_NO_LOAD_FUNCTION);
75        return NULL;
76    }
77    pkey = e->load_privkey(e, key_id, ui_method, callback_data);
78    if (pkey == NULL) {
79        ERR_raise(ERR_LIB_ENGINE, ENGINE_R_FAILED_LOADING_PRIVATE_KEY);
80        return NULL;
81    }
82    /* We enforce check for legacy key */
83    switch (EVP_PKEY_get_id(pkey)) {
84    case EVP_PKEY_RSA:
85        {
86        RSA *rsa = EVP_PKEY_get1_RSA(pkey);
87        EVP_PKEY_set1_RSA(pkey, rsa);
88        RSA_free(rsa);
89        }
90        break;
91#  ifndef OPENSSL_NO_EC
92    case EVP_PKEY_SM2:
93    case EVP_PKEY_EC:
94        {
95        EC_KEY *ec = EVP_PKEY_get1_EC_KEY(pkey);
96        EVP_PKEY_set1_EC_KEY(pkey, ec);
97        EC_KEY_free(ec);
98        }
99        break;
100#  endif
101#  ifndef OPENSSL_NO_DSA
102    case EVP_PKEY_DSA:
103        {
104        DSA *dsa = EVP_PKEY_get1_DSA(pkey);
105        EVP_PKEY_set1_DSA(pkey, dsa);
106        DSA_free(dsa);
107        }
108        break;
109#endif
110#  ifndef OPENSSL_NO_DH
111    case EVP_PKEY_DH:
112        {
113        DH *dh = EVP_PKEY_get1_DH(pkey);
114        EVP_PKEY_set1_DH(pkey, dh);
115        DH_free(dh);
116        }
117        break;
118#endif
119    default:
120        /*Do nothing */
121        break;
122    }
123
124    return pkey;
125}
126
127EVP_PKEY *ENGINE_load_public_key(ENGINE *e, const char *key_id,
128                                 UI_METHOD *ui_method, void *callback_data)
129{
130    EVP_PKEY *pkey;
131
132    if (e == NULL) {
133        ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
134        return NULL;
135    }
136    if (!CRYPTO_THREAD_write_lock(global_engine_lock))
137        return NULL;
138    if (e->funct_ref == 0) {
139        CRYPTO_THREAD_unlock(global_engine_lock);
140        ERR_raise(ERR_LIB_ENGINE, ENGINE_R_NOT_INITIALISED);
141        return NULL;
142    }
143    CRYPTO_THREAD_unlock(global_engine_lock);
144    if (!e->load_pubkey) {
145        ERR_raise(ERR_LIB_ENGINE, ENGINE_R_NO_LOAD_FUNCTION);
146        return NULL;
147    }
148    pkey = e->load_pubkey(e, key_id, ui_method, callback_data);
149    if (pkey == NULL) {
150        ERR_raise(ERR_LIB_ENGINE, ENGINE_R_FAILED_LOADING_PUBLIC_KEY);
151        return NULL;
152    }
153    return pkey;
154}
155
156int ENGINE_load_ssl_client_cert(ENGINE *e, SSL *s,
157                                STACK_OF(X509_NAME) *ca_dn, X509 **pcert,
158                                EVP_PKEY **ppkey, STACK_OF(X509) **pother,
159                                UI_METHOD *ui_method, void *callback_data)
160{
161
162    if (e == NULL) {
163        ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
164        return 0;
165    }
166    if (!CRYPTO_THREAD_write_lock(global_engine_lock))
167        return 0;
168    if (e->funct_ref == 0) {
169        CRYPTO_THREAD_unlock(global_engine_lock);
170        ERR_raise(ERR_LIB_ENGINE, ENGINE_R_NOT_INITIALISED);
171        return 0;
172    }
173    CRYPTO_THREAD_unlock(global_engine_lock);
174    if (!e->load_ssl_client_cert) {
175        ERR_raise(ERR_LIB_ENGINE, ENGINE_R_NO_LOAD_FUNCTION);
176        return 0;
177    }
178    return e->load_ssl_client_cert(e, s, ca_dn, pcert, ppkey, pother,
179                                   ui_method, callback_data);
180}
181