1d4afb5ceSopenharmony_ci// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
2d4afb5ceSopenharmony_ci//
3d4afb5ceSopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License");
4d4afb5ceSopenharmony_ci// you may not use this file except in compliance with the License.
5d4afb5ceSopenharmony_ci// You may obtain a copy of the License at
6d4afb5ceSopenharmony_ci
7d4afb5ceSopenharmony_ci//     http://www.apache.org/licenses/LICENSE-2.0
8d4afb5ceSopenharmony_ci//
9d4afb5ceSopenharmony_ci// Unless required by applicable law or agreed to in writing, software
10d4afb5ceSopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS,
11d4afb5ceSopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12d4afb5ceSopenharmony_ci// See the License for the specific language governing permissions and
13d4afb5ceSopenharmony_ci// limitations under the License.
14d4afb5ceSopenharmony_ci
15d4afb5ceSopenharmony_ci#include "private-lib-core.h"
16d4afb5ceSopenharmony_ci
17d4afb5ceSopenharmony_ci#include "ssl_pkey.h"
18d4afb5ceSopenharmony_ci#include "ssl_methods.h"
19d4afb5ceSopenharmony_ci#include "ssl_dbg.h"
20d4afb5ceSopenharmony_ci#include "ssl_port.h"
21d4afb5ceSopenharmony_ci
22d4afb5ceSopenharmony_ci/**
23d4afb5ceSopenharmony_ci * @brief create a private key object according to input private key
24d4afb5ceSopenharmony_ci */
25d4afb5ceSopenharmony_ciEVP_PKEY* __EVP_PKEY_new(EVP_PKEY *ipk, void *rngctx)
26d4afb5ceSopenharmony_ci{
27d4afb5ceSopenharmony_ci    int ret;
28d4afb5ceSopenharmony_ci    EVP_PKEY *pkey;
29d4afb5ceSopenharmony_ci
30d4afb5ceSopenharmony_ci    pkey = ssl_mem_zalloc(sizeof(EVP_PKEY));
31d4afb5ceSopenharmony_ci    if (!pkey) {
32d4afb5ceSopenharmony_ci        SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "no enough memory > (pkey)");
33d4afb5ceSopenharmony_ci        goto no_mem;
34d4afb5ceSopenharmony_ci    }
35d4afb5ceSopenharmony_ci
36d4afb5ceSopenharmony_ci    if (ipk) {
37d4afb5ceSopenharmony_ci        pkey->method = ipk->method;
38d4afb5ceSopenharmony_ci    } else {
39d4afb5ceSopenharmony_ci        pkey->method = EVP_PKEY_method();
40d4afb5ceSopenharmony_ci    }
41d4afb5ceSopenharmony_ci
42d4afb5ceSopenharmony_ci    ret = EVP_PKEY_METHOD_CALL(new, pkey, ipk, rngctx);
43d4afb5ceSopenharmony_ci    if (ret) {
44d4afb5ceSopenharmony_ci        SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "EVP_PKEY_METHOD_CALL(new) return %d", ret);
45d4afb5ceSopenharmony_ci        goto failed;
46d4afb5ceSopenharmony_ci    }
47d4afb5ceSopenharmony_ci
48d4afb5ceSopenharmony_ci    return pkey;
49d4afb5ceSopenharmony_ci
50d4afb5ceSopenharmony_cifailed:
51d4afb5ceSopenharmony_ci    ssl_mem_free(pkey);
52d4afb5ceSopenharmony_cino_mem:
53d4afb5ceSopenharmony_ci    return NULL;
54d4afb5ceSopenharmony_ci}
55d4afb5ceSopenharmony_ci
56d4afb5ceSopenharmony_ci/**
57d4afb5ceSopenharmony_ci * @brief create a private key object
58d4afb5ceSopenharmony_ci */
59d4afb5ceSopenharmony_ciEVP_PKEY* EVP_PKEY_new(void *rngctx)
60d4afb5ceSopenharmony_ci{
61d4afb5ceSopenharmony_ci    return __EVP_PKEY_new(NULL, rngctx);
62d4afb5ceSopenharmony_ci}
63d4afb5ceSopenharmony_ci
64d4afb5ceSopenharmony_ci/**
65d4afb5ceSopenharmony_ci * @brief free a private key object
66d4afb5ceSopenharmony_ci */
67d4afb5ceSopenharmony_civoid EVP_PKEY_free(EVP_PKEY *pkey)
68d4afb5ceSopenharmony_ci{
69d4afb5ceSopenharmony_ci    SSL_ASSERT3(pkey);
70d4afb5ceSopenharmony_ci
71d4afb5ceSopenharmony_ci    EVP_PKEY_METHOD_CALL(free, pkey);
72d4afb5ceSopenharmony_ci
73d4afb5ceSopenharmony_ci    ssl_mem_free(pkey);
74d4afb5ceSopenharmony_ci}
75d4afb5ceSopenharmony_ci
76d4afb5ceSopenharmony_ci/**
77d4afb5ceSopenharmony_ci * @brief load a character key context into system context. If '*a' is pointed to the
78d4afb5ceSopenharmony_ci *        private key, then load key into it. Or create a new private key object
79d4afb5ceSopenharmony_ci */
80d4afb5ceSopenharmony_ciEVP_PKEY *d2i_PrivateKey(int type,
81d4afb5ceSopenharmony_ci                         EVP_PKEY **a,
82d4afb5ceSopenharmony_ci                         const unsigned char **pp,
83d4afb5ceSopenharmony_ci                         long length, void *rngctx)
84d4afb5ceSopenharmony_ci{
85d4afb5ceSopenharmony_ci    int m = 0;
86d4afb5ceSopenharmony_ci    int ret;
87d4afb5ceSopenharmony_ci    EVP_PKEY *pkey;
88d4afb5ceSopenharmony_ci
89d4afb5ceSopenharmony_ci    SSL_ASSERT2(pp);
90d4afb5ceSopenharmony_ci    SSL_ASSERT2(*pp);
91d4afb5ceSopenharmony_ci    SSL_ASSERT2(length);
92d4afb5ceSopenharmony_ci
93d4afb5ceSopenharmony_ci    if (a && *a) {
94d4afb5ceSopenharmony_ci        pkey = *a;
95d4afb5ceSopenharmony_ci    } else {
96d4afb5ceSopenharmony_ci        pkey = EVP_PKEY_new(rngctx);
97d4afb5ceSopenharmony_ci        if (!pkey) {
98d4afb5ceSopenharmony_ci            SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "EVP_PKEY_new() return NULL");
99d4afb5ceSopenharmony_ci            goto failed1;
100d4afb5ceSopenharmony_ci        }
101d4afb5ceSopenharmony_ci
102d4afb5ceSopenharmony_ci        m = 1;
103d4afb5ceSopenharmony_ci    }
104d4afb5ceSopenharmony_ci
105d4afb5ceSopenharmony_ci    ret = EVP_PKEY_METHOD_CALL(load, pkey, *pp, (int)length);
106d4afb5ceSopenharmony_ci    if (ret) {
107d4afb5ceSopenharmony_ci        SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "EVP_PKEY_METHOD_CALL(load) return %d", ret);
108d4afb5ceSopenharmony_ci        goto failed2;
109d4afb5ceSopenharmony_ci    }
110d4afb5ceSopenharmony_ci
111d4afb5ceSopenharmony_ci    if (a)
112d4afb5ceSopenharmony_ci        *a = pkey;
113d4afb5ceSopenharmony_ci
114d4afb5ceSopenharmony_ci    return pkey;
115d4afb5ceSopenharmony_ci
116d4afb5ceSopenharmony_cifailed2:
117d4afb5ceSopenharmony_ci    if (m)
118d4afb5ceSopenharmony_ci        EVP_PKEY_free(pkey);
119d4afb5ceSopenharmony_cifailed1:
120d4afb5ceSopenharmony_ci    return NULL;
121d4afb5ceSopenharmony_ci}
122d4afb5ceSopenharmony_ci
123d4afb5ceSopenharmony_ci/**
124d4afb5ceSopenharmony_ci * @brief set the SSL context private key
125d4afb5ceSopenharmony_ci */
126d4afb5ceSopenharmony_ciint SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey)
127d4afb5ceSopenharmony_ci{
128d4afb5ceSopenharmony_ci    SSL_ASSERT1(ctx);
129d4afb5ceSopenharmony_ci    SSL_ASSERT1(pkey);
130d4afb5ceSopenharmony_ci
131d4afb5ceSopenharmony_ci    if (ctx->cert->pkey == pkey)
132d4afb5ceSopenharmony_ci        return 1;
133d4afb5ceSopenharmony_ci
134d4afb5ceSopenharmony_ci    if (ctx->cert->pkey)
135d4afb5ceSopenharmony_ci        EVP_PKEY_free(ctx->cert->pkey);
136d4afb5ceSopenharmony_ci
137d4afb5ceSopenharmony_ci    ctx->cert->pkey = pkey;
138d4afb5ceSopenharmony_ci
139d4afb5ceSopenharmony_ci    return 1;
140d4afb5ceSopenharmony_ci}
141d4afb5ceSopenharmony_ci
142d4afb5ceSopenharmony_ci/**
143d4afb5ceSopenharmony_ci * @brief set the SSL private key
144d4afb5ceSopenharmony_ci */
145d4afb5ceSopenharmony_ciint SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey)
146d4afb5ceSopenharmony_ci{
147d4afb5ceSopenharmony_ci    SSL_ASSERT1(ssl);
148d4afb5ceSopenharmony_ci    SSL_ASSERT1(pkey);
149d4afb5ceSopenharmony_ci
150d4afb5ceSopenharmony_ci    if (ssl->cert->pkey == pkey)
151d4afb5ceSopenharmony_ci        return 1;
152d4afb5ceSopenharmony_ci
153d4afb5ceSopenharmony_ci    if (ssl->cert->pkey)
154d4afb5ceSopenharmony_ci        EVP_PKEY_free(ssl->cert->pkey);
155d4afb5ceSopenharmony_ci
156d4afb5ceSopenharmony_ci    ssl->cert->pkey = pkey;
157d4afb5ceSopenharmony_ci
158d4afb5ceSopenharmony_ci    return 1;
159d4afb5ceSopenharmony_ci}
160d4afb5ceSopenharmony_ci
161d4afb5ceSopenharmony_ci/**
162d4afb5ceSopenharmony_ci * @brief load private key into the SSL context
163d4afb5ceSopenharmony_ci */
164d4afb5ceSopenharmony_ciint SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx,
165d4afb5ceSopenharmony_ci                                const unsigned char *d, long len)
166d4afb5ceSopenharmony_ci{
167d4afb5ceSopenharmony_ci    int ret;
168d4afb5ceSopenharmony_ci    EVP_PKEY *pk;
169d4afb5ceSopenharmony_ci
170d4afb5ceSopenharmony_ci    pk = d2i_PrivateKey(0, NULL, &d, len, ctx->rngctx);
171d4afb5ceSopenharmony_ci    if (!pk) {
172d4afb5ceSopenharmony_ci        SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "d2i_PrivateKey() return NULL");
173d4afb5ceSopenharmony_ci        goto failed1;
174d4afb5ceSopenharmony_ci    }
175d4afb5ceSopenharmony_ci
176d4afb5ceSopenharmony_ci    ret = SSL_CTX_use_PrivateKey(ctx, pk);
177d4afb5ceSopenharmony_ci    if (!ret) {
178d4afb5ceSopenharmony_ci        SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "SSL_CTX_use_PrivateKey() return %d", ret);
179d4afb5ceSopenharmony_ci        goto failed2;
180d4afb5ceSopenharmony_ci    }
181d4afb5ceSopenharmony_ci
182d4afb5ceSopenharmony_ci    return 1;
183d4afb5ceSopenharmony_ci
184d4afb5ceSopenharmony_cifailed2:
185d4afb5ceSopenharmony_ci    EVP_PKEY_free(pk);
186d4afb5ceSopenharmony_cifailed1:
187d4afb5ceSopenharmony_ci    return 0;
188d4afb5ceSopenharmony_ci}
189d4afb5ceSopenharmony_ci
190d4afb5ceSopenharmony_ci/**
191d4afb5ceSopenharmony_ci * @brief load private key into the SSL
192d4afb5ceSopenharmony_ci */
193d4afb5ceSopenharmony_ciint SSL_use_PrivateKey_ASN1(int type, SSL *ssl,
194d4afb5ceSopenharmony_ci                                const unsigned char *d, long len)
195d4afb5ceSopenharmony_ci{
196d4afb5ceSopenharmony_ci    int ret;
197d4afb5ceSopenharmony_ci    EVP_PKEY *pk;
198d4afb5ceSopenharmony_ci
199d4afb5ceSopenharmony_ci    pk = d2i_PrivateKey(0, NULL, &d, len, ssl->ctx->rngctx);
200d4afb5ceSopenharmony_ci    if (!pk) {
201d4afb5ceSopenharmony_ci        SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "d2i_PrivateKey() return NULL");
202d4afb5ceSopenharmony_ci        goto failed1;
203d4afb5ceSopenharmony_ci    }
204d4afb5ceSopenharmony_ci
205d4afb5ceSopenharmony_ci    ret = SSL_use_PrivateKey(ssl, pk);
206d4afb5ceSopenharmony_ci    if (!ret) {
207d4afb5ceSopenharmony_ci        SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "SSL_use_PrivateKey() return %d", ret);
208d4afb5ceSopenharmony_ci        goto failed2;
209d4afb5ceSopenharmony_ci    }
210d4afb5ceSopenharmony_ci
211d4afb5ceSopenharmony_ci    return 1;
212d4afb5ceSopenharmony_ci
213d4afb5ceSopenharmony_cifailed2:
214d4afb5ceSopenharmony_ci    EVP_PKEY_free(pk);
215d4afb5ceSopenharmony_cifailed1:
216d4afb5ceSopenharmony_ci    return 0;
217d4afb5ceSopenharmony_ci}
218d4afb5ceSopenharmony_ci
219d4afb5ceSopenharmony_ci/**
220d4afb5ceSopenharmony_ci * @brief load the private key file into SSL context
221d4afb5ceSopenharmony_ci */
222d4afb5ceSopenharmony_ciint SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type)
223d4afb5ceSopenharmony_ci{
224d4afb5ceSopenharmony_ci    return 0;
225d4afb5ceSopenharmony_ci}
226d4afb5ceSopenharmony_ci
227d4afb5ceSopenharmony_ci/**
228d4afb5ceSopenharmony_ci * @brief load the private key file into SSL
229d4afb5ceSopenharmony_ci */
230d4afb5ceSopenharmony_ciint SSL_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type)
231d4afb5ceSopenharmony_ci{
232d4afb5ceSopenharmony_ci    return 0;
233d4afb5ceSopenharmony_ci}
234d4afb5ceSopenharmony_ci
235d4afb5ceSopenharmony_ci/**
236d4afb5ceSopenharmony_ci * @brief load the RSA ASN1 private key into SSL context
237d4afb5ceSopenharmony_ci */
238d4afb5ceSopenharmony_ciint SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d, long len)
239d4afb5ceSopenharmony_ci{
240d4afb5ceSopenharmony_ci    return SSL_CTX_use_PrivateKey_ASN1(0, ctx, d, len);
241d4afb5ceSopenharmony_ci}
242