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