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 "ssl_pkey.h"
16 #include "ssl_methods.h"
17 #include "ssl_dbg.h"
18 #include "ssl_port.h"
19 #include "openssl/bio.h"
20
21 /**
22 * @brief create a private key object according to input private key
23 */
__EVP_PKEY_new(EVP_PKEY * ipk)24 EVP_PKEY* __EVP_PKEY_new(EVP_PKEY *ipk)
25 {
26 int ret;
27 EVP_PKEY *pkey;
28
29 pkey = ssl_mem_zalloc(sizeof(EVP_PKEY));
30 if (!pkey) {
31 SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "no enough memory > (pkey)");
32 goto no_mem;
33 }
34
35 pkey->ref_counter = 1;
36
37 if (ipk) {
38 pkey->method = ipk->method;
39 } else {
40 pkey->method = EVP_PKEY_method();
41 }
42
43 ret = EVP_PKEY_METHOD_CALL(new, pkey, ipk);
44 if (ret) {
45 SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "EVP_PKEY_METHOD_CALL(new) return %d", ret);
46 goto failed;
47 }
48
49 return pkey;
50
51 failed:
52 ssl_mem_free(pkey);
53 no_mem:
54 return NULL;
55 }
56
57 /**
58 * @brief create a private key object
59 */
EVP_PKEY_new(void)60 EVP_PKEY* EVP_PKEY_new(void)
61 {
62 return __EVP_PKEY_new(NULL);
63 }
64
65 /**
66 * @brief free a private key object
67 */
EVP_PKEY_free(EVP_PKEY * pkey)68 void EVP_PKEY_free(EVP_PKEY *pkey)
69 {
70 SSL_ASSERT3(pkey);
71
72 if (--pkey->ref_counter > 0) {
73 return;
74 }
75
76 EVP_PKEY_METHOD_CALL(free, pkey);
77
78 ssl_mem_free(pkey);
79 }
80
81 /**
82 * @brief load a character key context into system context. If '*a' is pointed to the
83 * private key, then load key into it. Or create a new private key object
84 */
d2i_PrivateKey(int type,EVP_PKEY ** a,const unsigned char ** pp,long length)85 EVP_PKEY *d2i_PrivateKey(int type,
86 EVP_PKEY **a,
87 const unsigned char **pp,
88 long length)
89 {
90 int m = 0;
91 int ret;
92 EVP_PKEY *pkey;
93
94 SSL_ASSERT2(pp);
95 SSL_ASSERT2(*pp);
96 SSL_ASSERT2(length);
97
98 if (a && *a) {
99 pkey = *a;
100 } else {
101 pkey = EVP_PKEY_new();;
102 if (!pkey) {
103 SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "EVP_PKEY_new() return NULL");
104 goto failed1;
105 }
106
107 m = 1;
108 }
109
110 ret = EVP_PKEY_METHOD_CALL(load, pkey, *pp, length);
111 if (ret) {
112 SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "EVP_PKEY_METHOD_CALL(load) return %d", ret);
113 goto failed2;
114 }
115
116 if (a)
117 *a = pkey;
118
119 return pkey;
120
121 failed2:
122 if (m)
123 EVP_PKEY_free(pkey);
124 failed1:
125 return NULL;
126 }
127
d2i_PrivateKey_bio(BIO * bp,EVP_PKEY ** a)128 EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a)
129 {
130 return d2i_PrivateKey(0, a, (const unsigned char **)&bp->data, bp->dlen);
131 }
132
d2i_RSAPrivateKey_bio(BIO * bp,RSA ** a)133 RSA *d2i_RSAPrivateKey_bio(BIO *bp,RSA **a)
134 {
135 return d2i_PrivateKey_bio(bp, (EVP_PKEY**)a);
136 }
137
PEM_read_bio_RSAPrivateKey(BIO * bp,RSA ** x,pem_password_cb * cb,void * u)138 RSA *PEM_read_bio_RSAPrivateKey(BIO *bp, RSA **x, pem_password_cb *cb, void *u)
139 {
140 return PEM_read_bio_PrivateKey(bp, (EVP_PKEY**)x, cb, u);
141 }
142
PEM_read_bio_PrivateKey(BIO * bp,EVP_PKEY ** pk,pem_password_cb * cb,void * u)143 EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **pk, pem_password_cb *cb, void *u)
144 {
145
146 int m = 0;
147 int ret;
148 EVP_PKEY *x;
149
150 SSL_ASSERT2(BIO_method_type(bp) & BIO_TYPE_MEM);
151 if (bp->data == NULL || bp->dlen == 0) {
152 return NULL;
153 }
154 if (pk && *pk) {
155 x = *pk;
156 } else {
157 x = EVP_PKEY_new();
158 if (!x) {
159 SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "EVP_PKEY_new() return NULL");
160 goto failed;
161 }
162 m = 1;
163 }
164
165 ret = EVP_PKEY_METHOD_CALL(load, x, bp->data, bp->dlen);
166 if (ret) {
167 SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "EVP_PKEY_METHOD_CALL(load) return %d", ret);
168 goto failed;
169 }
170
171 // If buffer successfully created a EVP_PKEY from the bio, mark the buffer as consumed
172 bp->data = NULL;
173 bp->dlen = 0;
174 return x;
175
176 failed:
177 if (m) {
178 EVP_PKEY_free(x);
179 }
180
181 return NULL;}
182 /**
183 * @brief set the SSL context private key
184 */
SSL_CTX_use_PrivateKey(SSL_CTX * ctx,EVP_PKEY * pkey)185 int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey)
186 {
187 SSL_ASSERT1(ctx);
188 SSL_ASSERT1(pkey);
189
190 if (ctx->cert->pkey == pkey)
191 return 1;
192
193 if (ctx->cert->pkey)
194 EVP_PKEY_free(ctx->cert->pkey);
195
196 pkey->ref_counter++;
197 ctx->cert->pkey = pkey;
198
199 return 1;
200 }
201
202 /**
203 * @brief set the SSL private key
204 */
SSL_use_PrivateKey(SSL * ssl,EVP_PKEY * pkey)205 int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey)
206 {
207 SSL_ASSERT1(ssl);
208 SSL_ASSERT1(pkey);
209
210 if (ssl->cert->pkey == pkey)
211 return 1;
212
213 if (ssl->cert->pkey)
214 EVP_PKEY_free(ssl->cert->pkey);
215
216 ssl->cert->pkey = pkey;
217
218 return 1;
219 }
220
221 /**
222 * @brief load private key into the SSL context
223 */
SSL_CTX_use_PrivateKey_ASN1(int type,SSL_CTX * ctx,const unsigned char * d,long len)224 int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx,
225 const unsigned char *d, long len)
226 {
227 int ret;
228 EVP_PKEY *pk;
229
230 pk = d2i_PrivateKey(0, NULL, &d, len);
231 if (!pk) {
232 SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "d2i_PrivateKey() return NULL");
233 goto failed1;
234 }
235
236 ret = SSL_CTX_use_PrivateKey(ctx, pk);
237 if (!ret) {
238 SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "SSL_CTX_use_PrivateKey() return %d", ret);
239 goto failed2;
240 }
241
242 return 1;
243
244 failed2:
245 EVP_PKEY_free(pk);
246 failed1:
247 return 0;
248 }
249
250 /**
251 * @brief load private key into the SSL
252 */
SSL_use_PrivateKey_ASN1(int type,SSL * ssl,const unsigned char * d,long len)253 int SSL_use_PrivateKey_ASN1(int type, SSL *ssl,
254 const unsigned char *d, long len)
255 {
256 int ret;
257 EVP_PKEY *pk;
258
259 pk = d2i_PrivateKey(0, NULL, &d, len);
260 if (!pk) {
261 SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "d2i_PrivateKey() return NULL");
262 goto failed1;
263 }
264
265 ret = SSL_use_PrivateKey(ssl, pk);
266 if (!ret) {
267 SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "SSL_use_PrivateKey() return %d", ret);
268 goto failed2;
269 }
270
271 return 1;
272
273 failed2:
274 EVP_PKEY_free(pk);
275 failed1:
276 return 0;
277 }
278
279 #define ESP_OPENSSL_FILES_IS_SUPPORTED 0
280 /**
281 * @brief load the private key file into SSL context
282 */
SSL_CTX_use_PrivateKey_file(SSL_CTX * ctx,const char * file,int type)283 int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type)
284 {
285 // Using file name as private key is discouraged
286 SSL_ASSERT1(ESP_OPENSSL_FILES_IS_SUPPORTED);
287 return -1;
288 }
289
290 /**
291 * @brief load the private key file into SSL
292 */
SSL_use_PrivateKey_file(SSL_CTX * ctx,const char * file,int type)293 int SSL_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type)
294 {
295 // Using file name as private key is discouraged
296 SSL_ASSERT1(ESP_OPENSSL_FILES_IS_SUPPORTED);
297 return -1;
298 }
299
300 /**
301 * @brief load the RSA ASN1 private key into SSL context
302 */
SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX * ctx,const unsigned char * d,long len)303 int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d, long len)
304 {
305 return SSL_CTX_use_PrivateKey_ASN1(0, ctx, d, len);
306 }
307
RSA_free(RSA * r)308 void RSA_free (RSA *r)
309 {
310 EVP_PKEY_free(r);
311 }
312